System Design: Designing a Real-time Gaming Leaderboard
A leaderboard is a core feature in competitive gaming and fitness apps. While a simple SQL ORDER BY works for 100 users, doing it for 100 million users with real-time updates is a major scalability challenge.
1. Core Requirements
- Real-time Updates: A user's rank should update immediately after they earn points.
- Top K Query: Fetching the top 10 or 100 players globally.
- Relative Rank Query: Fetching a user's current rank and the players immediately above and below them.
- Scalability: Handling millions of players and high-frequency score updates.
2. The Solution: Redis Sorted Sets (ZSET)
The industry standard for leaderboards is Redis Sorted Sets.
- Internal Structure: A ZSET uses a combination of a Hash Map (for (1)$ score lookups) and a Skip List (for (\log N)$ rank updates and range queries).
- Efficiency: You can update a score and find a user's rank among millions of players in logarithmic time.
Common Commands:
ZADD leaderboard <score> <player_id>: Update score.ZREVRANGE leaderboard 0 99: Get the top 100 players.ZREVRANK leaderboard <player_id>: Get a specific user's rank.
3. Scaling Beyond a Single Redis Node
A single Redis instance can hold millions of users, but eventually, you'll hit a memory or CPU limit.
- The Problem: You cannot easily shard a leaderboard because rank is a global property.
- The Solution: Sharding by Score Range.
- Shard 1: Scores 0 - 1,000.
- Shard 2: Scores 1,001 - 2,000.
- ...and so on.
- Aggregating: To find the global rank, you query the counts in all shards with higher score ranges and add the user's rank in their current shard.
4. Handling Daily, Weekly, and Monthly Leaderboards
- Multiple Keys: Store scores in different Redis keys:
leaderboard:daily:2024-04-20,leaderboard:weekly:2024-W16. - Automatic Cleanup: Use Redis
EXPIREto automatically delete old daily leaderboards and save memory.
5. Storage and Durability
Redis is primarily in-memory. For durability:
- Write-Through: Every score update is also sent to a persistent relational database (Postgres/MySQL) via a message queue (Kafka).
- Recovery: If Redis crashes, the leaderboard is reconstructed by querying the SQL database.
6. Caching for High Read Volume
The "Top 10" list is requested by every user every time they open the app.
- Optimization: Cache the Top 10 list in an application-level cache (or a separate Redis key) and update it every 1-5 seconds to reduce the load on the main ZSET.
Summary
Building a leaderboard is about choosing the right data structure. By leveraging the (\log N)$ performance of Redis Sorted Sets and implementing a sharding strategy for global scale, you can provide an instant, competitive experience for millions of users worldwide.
