Lesson 2
Using Sorted Sets to Create Dynamic Leaderboards in Redis
Using Sorted Sets for Leaderboards

Welcome to the next exciting part of our Redis-based backend system project. In this unit, we will focus on building leaderboard functionality using Redis's sorted sets. Building a leaderboard is a popular use case for many applications, such as games and competitive platforms. You’ve got a good handle on managing user data from previous lessons, so let’s build on that foundation.

What You'll Build

In this unit, we will work on three main tasks:

  1. Adding user scores to a leaderboard: Use Redis's sorted sets to store user scores efficiently.
  2. Retrieving the leaderboard: Fetch and display the top users along with their scores.
  3. Getting a user's rank and score: Retrieve a specific user's ranking and score from the leaderboard.

These tasks will demonstrate how Redis sorted sets help maintain order and provide efficient rank-based queries.

Adding User Scores to a Leaderboard

To add user scores to a leaderboard, we’ll use Redis’s zadd command. In Java, the zadd method of Jedis allows us to add a user with an associated score to a sorted set. Here’s the relevant portion of the User class:

Java
1// Add user score to the leaderboard using a pipeline 2public static void addScoreWithPipeline(Pipeline pipeline, User user) { 3 pipeline.zadd("leaderboard", user.getScore(), user.getUsername()); 4}

This method adds the user’s score to the "leaderboard" sorted set. As a reminder, pipelines allow multiple commands to be sent in one go, improving performance by reducing network latency.

In the Main class, this method is called for each user:

Java
1try (Pipeline pipeline = jedis.pipelined()) { 2 for (User user : new User[]{user1, user2, user3}) { 3 User.addScoreWithPipeline(pipeline, user); 4 } 5 pipeline.sync(); 6}

This snippet adds scores for multiple users in one batch operation with reduced communication overhead.

Retrieving the Leaderboard

To fetch and display the top users and their scores, we use Redis’s zrevrange command, which retrieves elements in descending order of scores. The getLeaderboard method handles this:

Java
1// Retrieve the top 10 users from the leaderboard 2public static List<Tuple> getLeaderboard(Jedis jedis) { 3 return jedis.zrevrangeWithScores("leaderboard", 0, 9); 4}

Here’s how it’s used in the Main class to display the leaderboard:

Java
1System.out.println("Leaderboard: " + User.getLeaderboard(jedis));

This outputs a list of the top 10 users with their scores, formatted as [[username, score], ...].

Getting a User's Rank and Score

To retrieve a user’s rank and score, we use the zrevrank and zscore commands. The getUserRankAndScore method combines these two operations:

Java
1// Get a user's rank and score from the leaderboard 2public static RankScore getUserRankAndScore(Jedis jedis, String username) { 3 Long rank = jedis.zrevrank("leaderboard", username); // 0-based rank 4 Double score = jedis.zscore("leaderboard", username); 5 return new RankScore(rank != null ? rank + 1 : -1, score != null ? score : 0.0); 6}

The zrevrank command retrieves the user’s rank (with the highest score ranked first), and the zscore command retrieves the user’s score.

In the Main class, this is how ranks and scores are displayed:

Java
1for (User user : new User[]{user1, user2, user3}) { 2 RankScore rankScore = User.getUserRankAndScore(jedis, user.getUsername()); 3 System.out.println("User " + user.getUsername() + " rank: " + rankScore.getRank() + ", score: " + rankScore.getScore()); 4}

For each user, this prints their rank and score.

Why It Matters

Leaderboards are a common feature in many applications, especially in gaming and competitive platforms. With Redis’s sorted sets, you can efficiently store, retrieve, and manage ranked data, enabling real-time leaderboard updates and rank queries. This lesson equips you with the tools to implement robust, scalable leaderboard systems for your backend.

Now that you have an overview, let's dive into the practice section to start implementing these components. Your hands-on work will strengthen your understanding, setting you up for success in creating robust backend features.

Enjoy this lesson? Now it's time to practice with Cosmo!
Practice is how you turn knowledge into actual skills.