← Redis
Production Battleground & Post-Mortems

Redis Real-World Case Studies & Architectural Failures

Dissecting Hardware Limits, NIC Saturation, OOM Killers, and Cascading Failures at GitHub, Twitter (X), Slack, and Grab/Uber

การเข้าใจทฤษฎี In-Memory และ Event Loop ทำให้เราสร้างระบบที่เร็วได้ แต่การเข้าใจ "จุดพังพินาศในสมรภูมิจริง" (Real-World Battleground Post-Mortems) คือสิ่งที่แยกความแตกต่างระหว่างวิศวกรทั่วไปกับระดับ Lead Distributed Systems Architect

ในคู่มือฉบับนี้ เราจะผ่าชันสูตร 4 มหากาพย์ความพังพินาศระดับโลก เมื่อ Redis ชนเพดานข้อจำกัดทางกายภาพของฮาร์ดแวร์ ทั้ง Network Interface Card (NIC), Linux Copy-on-Write (COW), Replication Buffer Overflow, และ Volatile Memory Eviction Traps

Case Study 1: GitHub — การพังทลายของ 100 Gbps Network Interface จาก Big Key ใน Queue

1. บริบทและสถาปัตยกรรมเดิม (Background Context)

GitHub ใช้งาน Redis เป็นกระดูกสันหลังในการจัดการ Background Job Processing ผ่านระบบที่ชื่อว่า Resque โดยรองรับงานประมวลผล Webhook, Git Push Ingestion, CI/CD Actions, และ Event Fan-out นับล้านงานต่อวัน

[ Webhook / Push Event ] | v +-----------------------+ LPUSH queue:jobs { "diff": "2MB JSON...", ... } | GitHub Web App (JVM) | -------------------------------------------------+ +-----------------------+ | v +---------------------------------------+ | REDIS RESQUE CLUSTER | | | | Key: "queue:default" | | [ 2MB Payload ] -> [ 1.8MB Payload ] | +---------------------------------------+ | | BRPOP (10,000 req/sec) v [ 1,000+ Resque Workers ] (10,000 x 2MB = 20 GB/s Traffic) (Exceeds 100 Gbps = 12.5 GB/s NIC Limit!)

2. สาเหตุทางสถาปัตยกรรมระดับลึก (Architectural Root Cause)

3. การแก้ไขเชิงสถาปัตยกรรม (Architectural Solution)

นำหลักการ Pointer-Only Queue Pattern (Claim Check Pattern) มาปรับใช้:

// ARCHITECTURAL REFACTORING: Kotlin Implementation
data class JobClaimCheck(
    val jobId: String,
    val payloadStorageUri: String // บันทึกเฉพาะ Pointer ชี้ไปยัง Blob Storage
)

@Service
class ResqueProducer(
    private val redisTemplate: StringRedisTemplate,
    private val s3Client: AmazonS3
) {
    fun enqueueHeavyJob(jobId: String, largePayload: ByteArray) {
        // Step 1: ผลัก Large Payload ออกจาก Redis ไปเก็บใน S3
        val uri = "s3://github-jobs-bucket/payloads/" + jobId + ".json"
        s3Client.putObject("github-jobs-bucket", "payloads/" + jobId + ".json", largePayload.inputStream(), null)

        // Step 2: Redis List บันทึกเฉพาะ Pointer ขนาดเล็ก (ไม่เกิน 100 Bytes)
        val claimCheckJson = "{\"jobId\":\"" + jobId + "\",\"uri\":\"" + uri + "\"}"
        redisTemplate.opsForList().leftPush("queue:default", claimCheckJson)
        // Network Bandwidth ลดลงทันที 99.99%! (จาก 2MB เหลือ 100 Bytes ต่อ Job)
    }
}
Engineering References & Sources:
• GitHub Engineering Blog: "How GitHub Deals with Background Jobs at Scale"
• Resque Architecture Specification by Chris Wanstrath (GitHub Co-founder)

Case Study 2: Twitter (X) — Celebrity Fan-Out & Timeline ZSet Crisis

1. บริบทและสถาปัตยกรรมเดิม (Background Context)

ระบบ Home Timeline ของ Twitter อาศัยการทำ Fan-out on Write โดยทวีตใหม่จะถูกนำ ID ไปแทรกลงใน In-Memory List หรือ Sorted Set ของ Follower ทุกคน เพื่อให้การเปิดแอปมาอ่านฟีด (Read Path) ทำได้รวดเร็วในระดับ Sub-10ms

[ Celebrity Tweet ] (e.g. 50,000,000 Followers) | v +-------------------------------------------------------------+ | Fan-out Ingestion Daemon | +-------------------------------------------------------------+ | +-- Write to Follower 1 (acc:101) -> LPUSH / ZADD +-- Write to Follower 2 (acc:102) -> LPUSH / ZADD : +-- Write to Follower 50M (acc:50M) -> LPUSH / ZADD | v [ 50,000,000 Writes to Redis in seconds! ] -> Huge Memory Latency Spike & Single Thread Lockup

2. สาเหตุทางสถาปัตยกรรมระดับลึก (Architectural Root Cause)

3. การแก้ไขเชิงสถาปัตยกรรม (Architectural Solution)

Engineering References & Sources:
• InfoQ / Twitter Engineering: "Timelines at Scale" (Raffi Krikorian, VP of Platform Engineering)
• High Scalability: "How Twitter Serves Over 100 Million Timelines"

Case Study 3: Slack — Disaster Recovery Failover ที่ทำให้เกิด Replication Buffer OOM

1. บริบทและสถาปัตยกรรมเดิม (Background Context)

Slack พึ่งพา Redis อย่างหนักในการจัดการ State แบบ Real-time เช่น Presence Tracking (สถานะออนไลน์/ออฟไลน์), Unread Message Badges, และ Channel Member State ของผู้ใช้นับสิบล้านคน โดยวาง Topology แบบ Master-Replica พร้อม Sentinel Quorum

+------------------------------------------------------+ | REDIS MASTER (120GB RAM) | | | | 1. Network Glitch -> Sentinel triggers Failover | | 2. Replica requests PSYNC | | 3. Backlog Buffer Full -> Falls back to FULL SYNC | | 4. fork() -> BGSAVE (120GB Dump) | | | | [ Incoming Client Writes: 50,000 ops/sec ] | | | | | v | | [ client-output-buffer-limit slave (RAM Overflow) ] | | | | | v | | Linux Kernel OOM Killer executes: SIGKILL redis-server! +------------------------------------------------------+

2. สาเหตุทางสถาปัตยกรรมระดับลึก (Architectural Root Cause)

3. การแก้ไขเชิงสถาปัตยกรรม (Architectural Solution)

Engineering References & Sources:
• Slack Engineering Blog: "Scaling Slack's Cache: Lessons Learned from Massive Scale"
• AWS / Redis Labs Case Study: "Slack's Real-time Messaging Architecture"

Case Study 4: Grab / Uber — Geo-Distributed Driver Dispatch & Memory Eviction Loss

1. บริบทและสถาปัตยกรรมเดิม (Background Context)

ระบบ Real-time Driver Dispatch ของแอปเรียกรถอย่าง Grab และ Uber อาศัย Redis GEO (เช่น GEOADD, GEORADIUS / GEOSEARCH) ในการระบุพิกัดคนขับนับแสนคนเพื่อจับคู่กับผู้โดยสารที่ใกล้ที่สุดภายในเสี้ยววินาที โดยเบื้องหลัง Redis จะแปลงละติจูด/ลองจิจูดเป็น 52-bit Geohash Integer บรรจุลงใน Sorted Set (ZSet)

Drivers' GPS Updates (Every 3 seconds) | v +-----------------------------------------------------------+ | Redis Cluster: Key = "drivers:geo:bangkok" (ZSet/Geohash) | | | | Memory Policy: volatile-lru | | Key TTL: None (Forgotten!) | +-----------------------------------------------------------+ | v [ RAM hits maxmemory limit (e.g. 32GB) ] | v (volatile-lru searches for keys WITH TTL to evict) [ NO KEYS WITH TTL FOUND! ] | v Redis halts all WRITES and throws: "OOM command not allowed when used memory > 'maxmemory'" | v [ Dispatch System Down: Drivers' GPS frozen, No cars available! ]

2. สาเหตุทางสถาปัตยกรรมระดับลึก (Architectural Root Cause)

3. การแก้ไขเชิงสถาปัตยกรรม (Architectural Solution)

Engineering References & Sources:
• Grab Tech Blog: "How Grab Uses Redis for Real-time Geospatial Querying"
• Uber Engineering: "Manifold: Large-Scale Geospatial Indexing and Dispatch"

Production Post-Mortem Assessment Bank (Interactive Knowledge Check)

ทดสอบความเข้าใจเชิงลึกเกี่ยวกับข้อจำกัดทางฮาร์ดแวร์ ปัญหา Network Saturation และการป้องกันวิกฤตระดับ Production จากกรณีศึกษาจริง 10 ข้อ

Post-Mortem Score: 0 / 10