How Discord Stores TRILLIONS of Messages
Summary of How Discord Stores TRILLIONS of Messages from ByteByteGo · Published 2023-06-15 · Views: 197,549
This note was generated automatically from the video transcript.
TL;R
Discord migrated a trillion‑plus message store from Cassandra (177 nodes) to ScyllaDB (72 nodes) in nine days with zero downtime. The success hinged on a Rust‑based data‑service layer for request coalescing and a custom “super‑disk” that combined local SSDs (RAID‑0) for fast reads with Google Persistent Disks (RAID‑1) for durable writes.
Key Insights
- Incremental migrations on smaller clusters let the team validate tooling and processes before tackling the massive “cassandra‑messages” cluster.
- ScyllaDB provides Cassandra‑compatible semantics with a C++ engine that eliminates garbage‑collection pauses, dramatically improving latency and repair speed.
- A Rust data‑service layer sits between the API monolith and the databases, performing request coalescing to avoid hot‑partition spikes.
- The “super‑disk” is a two‑layer RAID: RAID‑0 across multiple local SSDs for low‑latency reads, mirrored (RAID‑1) to a Persistent Disk for durable writes.
- Linux kernel write‑path redirection ensures every write lands on the Persistent Disk while reads are served from the SSD array, achieving both speed and reliability.
- The entire migration was executed by a purpose‑built Rust migrator, completing the transfer of trillions of rows in nine days without service interruption.
- Post‑migration, node count dropped from 177 to 72, cutting operational overhead and on‑call incidents while delivering consistently lower query latency.
Detailed Breakdown
1. Problem Context & Motivation
Discord’s primary message store ran on Cassandra, a NoSQL database that, by 2022, spanned 177 nodes and held trillions of messages. The cluster suffered:
- Unpredictable latency spikes.
- Frequent on‑call incidents due to repair and GC pauses.
- High operational toil maintaining the large node pool.
A more performant, low‑maintenance solution was required to keep Discord’s core chat experience responsive.
2. Choosing ScyllaDB
ScyllaDB is a Cassandra‑compatible database built in C++. Its advantages:
- Garbage‑collection‑free runtime, eliminating the GC‑induced latency seen in Cassandra.
- Faster repair mechanisms and higher throughput per node.
- Compatibility allowed a drop‑in migration path without rewriting query logic.
3. Incremental Migration Strategy
Rather than a “big bang” switch, Discord first migrated smaller, non‑critical databases to:
- Validate tooling (e.g., data migrator, monitoring).
- Surface hidden incompatibilities.
- Refine operational playbooks.
Only after confidence was built did they target the massive cassandra‑messages cluster.
4. Data Services Layer (Rust)
A new service, written in Rust, was introduced between the API monolith and the database clusters.
- Request Coalescing: When multiple clients request the same message or channel data, the service deduplicates the DB call, issuing a single query and broadcasting the result to all awaiting clients.
- This dramatically reduces the chance of hot partitions, especially in large servers with frequent
@everyonepings.
flowchart LR
client["Client"] --> api["API Monolith"]
api --> ds["Data Services (Rust)"]
ds --> db["ScyllaDB Cluster"]
ds --> cache["Cache (optional)"]
ds --> db
5. The “Super‑Disk” Solution
Discord’s workload required ultra‑low read latency but also strong durability for writes. Neither local NVMe SSDs (fast but volatile) nor Google Persistent Disks (durable but higher latency) alone satisfied both constraints.
Design:
- RAID‑0 across several Local SSDs → creates a single high‑throughput, low‑latency virtual disk for reads.
- RAID‑1 mirrors the RAID‑0 array to a Google Persistent Disk → guarantees durability.
- Kernel configuration directs writes to the Persistent Disk while reads are served from the SSD array.
flowchart LR
app["ScyllaDB Nodes"] --> raid0["RAID0 (Local SSDs)"]
raid0 --> read["Read Path (low latency)"]
raid0 --> raid1["RAID1 Mirror"]
raid1 --> pd["Persistent Disk (writes)"]
pd --> durability["Durable Writes"]
Result: At peak load, disk queues vanished and query latency remained stable.
6. Migration Execution
- A custom Rust migrator streamed data from Cassandra to ScyllaDB.
- Migration window: 9 days (≈216 hours) with zero downtime.
- Process involved:
- Snapshotting Cassandra tables.
- Streaming rows in parallel across multiple migrator instances.
- Verifying row counts and checksum integrity.
- Switchover of traffic to ScyllaDB once consistency thresholds were met.
7. Post‑Migration Outcomes
- Node count reduced from 177 Cassandra to 72 ScyllaDB nodes.
- Latency became more predictable; on‑call incidents dropped sharply.
- Operational cost and maintenance overhead decreased significantly.
Trade‑offs and Gotchas
- Compatibility vs. Performance: ScyllaDB’s Cassandra‑compatible API eased migration but required careful tuning of compaction and memory settings to unlock its performance.
- Super‑Disk Complexity: Managing a custom RAID‑0+RAID‑1 stack adds operational complexity (monitoring RAID health, kernel tuning) and ties the solution to Google Cloud’s VM and disk offerings.
- Write Path Bottleneck: Directing all writes to Persistent Disk can become a bottleneck under extreme write spikes; capacity planning for the PD is essential.
- Request Coalescing Limits: Coalescing works best for hot, identical reads; divergent queries still hit the DB, so cache warm‑up strategies remain important.
- Migration Validation: Ensuring data fidelity at trillions‑scale required robust checksum and spot‑check mechanisms; any oversight could lead to silent data loss.
Takeaways
- Prototype on smaller workloads before scaling a risky migration to production‑critical data.
- Leverage compatible drop‑in replacements (ScyllaDB for Cassandra) to minimize application changes while gaining performance.
- Insert a thin, high‑performance service layer (Rust data services) to implement request coalescing and protect the DB from hot‑spot storms.
- Build storage solutions from first principles when off‑the‑shelf options don’t meet latency‑durability trade‑offs.
- Automate migration with purpose‑built tooling and rigorous validation to achieve zero‑downtime moves at massive scale.
Glossary
- Cassandra: A distributed NoSQL database optimized for high write throughput, using a Java runtime with garbage collection.
- ScyllaDB: A drop‑in replacement for Cassandra written in C++, offering higher performance and no GC pauses.
- RAID0: Striping across multiple disks to increase throughput and reduce latency, without redundancy.
- RAID1: Mirroring data across disks for redundancy and durability.
- Persistent Disk: Google Cloud’s network‑attached block storage offering durability guarantees.
- Local SSD: High‑performance, physically attached SSDs on a VM instance, offering low latency but limited durability.
- Request Coalescing: Merging multiple identical read requests into a single backend query and sharing the result.
- Data Services (Rust): A micro‑service layer written in Rust that sits between the API and the database, handling request deduplication and other cross‑cutting concerns.
Leave a comment