A Danmaku System from Standalone to Million-User Clusters
The same push-broadcast-store pipeline underpins any real-time group chat, live-auction feed, or collaborative editing tool. The hot-cold storage pattern and the ban on synchronous DB writes are the two rules that keep latency flat and the database alive under spike traffic.
A danmaku system needs to push messages to every viewer in a live room with sub-100ms latency. HTTP polling collapses under load, so the architecture switches to WebSocket persistent connections via Netty, which keeps 50,000–100,000 connections alive on a single 4-core 8GB machine. When traffic outgrows one server, a message queue like RocketMQ broadcasts each comment to every cluster node, and Redis Pub/Sub handles smaller deployments where occasional message loss is acceptable.
Storage uses a hot-cold split: the most recent 500 messages per room sit in a Redis sorted set for instant retrieval, while all history flows asynchronously through a message queue into MySQL in batches of 1,000 rows. Synchronous database writes are avoided entirely to prevent the main push pipeline from blocking. Rate limiting is enforced with a Lua-scripted sliding window in Redis, and a DFA-based filter scans text in a single pass for sensitive words.
On the frontend, Canvas rendering replaces DOM manipulation once message volume climbs, recycling vertical tracks as text scrolls off-screen. The system also batches outbound pushes every 50ms, caches hot-room data locally with Caffeine, and isolates celebrity-stream traffic onto dedicated server resources. The roadmap moves from HTTP polling under 10,000 users to a multi-datacenter service mesh above one million.
The architecture is a textbook exercise in separating the fast path from the slow path: Redis acknowledges the user in ~1ms while MySQL catches up later, a pattern that applies to any write-heavy real-time feed.
Choosing between Redis Pub/Sub and a full message queue is framed as a reliability-vs-ops trade-off, not a purity test, which matches how teams actually decide under delivery pressure.
The DFA filter is a reminder that a well-known CS algorithm beats a regex loop when the word list is large and the text is short, a detail often missed in quick implementations.
The 50ms batch-push scheduler is a low-effort, high-impact optimization that turns per-message IO into a periodic bulk write, a trick that generalizes to any fan-out system.