Sets and Sorted Sets

[!NOTE] This module explores the core principles of Sets and Sorted Sets, deriving solutions from first principles and hardware constraints to build world-class, production-ready expertise.

1. Sets: Unordered & Unique

Redis Sets store unique strings. They are perfect for filtering duplicates and performing set theory operations.

  • Complexity: O(1) for Add/Remove/Check.
  • Internals: Hashtable (or IntSet if small integers).

Use Case: Common Friends (Intersection)

User A follows [1, 2, 3]. User B follows [2, 3, 4]. Common: [2, 3].

Java

jedis.sadd("user:A:follows", "1", "2", "3");
jedis.sadd("user:B:follows", "2", "3", "4");

// SINTER = Set Intersection
Set<String> common = jedis.sinter("user:A:follows", "user:B:follows");
// Returns ["2", "3"]

Go

rdb.SAdd(ctx, "user:A:follows", "1", "2", "3")
rdb.SAdd(ctx, "user:B:follows", "2", "3", "4")

common, _ := rdb.SInter(ctx, "user:A:follows", "user:B:follows").Result()
// Returns ["2", "3"]

2. Sorted Sets (ZSets): The Crown Jewel

ZSets are unique strings ordered by a floating-point Score. This is Redis’s most powerful structure.

  • Complexity: O(log N) for Add/Remove/Rank.
  • Use Cases: Leaderboards, Priority Queues, Rate Limiting (Sliding Window).

Internals: The Skip List

How does Redis maintain order efficiently? It uses a Skip List.

  • Linked List: O(N) search.
  • Skip List: Adds layers of “express lanes” to skip over elements. Complexity becomes O(log N) on average.

3. Interactive: Skip List Visualizer

Search for 50. See how we skip the lower levels to find it faster.

Ready

4. Real-World Example: Gaming Leaderboard

Store millions of players and get the top 10 in milliseconds.

Java

// 1. Update Score
jedis.zadd("leaderboard", 1500, "player_alice");

// 2. Get Top 3 (Reverse Range)
// 0 is first, 2 is third
List<String> top3 = jedis.zrevrange("leaderboard", 0, 2);

// 3. Get Rank of Alice
long rank = jedis.zrevrank("leaderboard", "player_alice");
// Returns 0 if first place

Go

// 1. Update Score
rdb.ZAdd(ctx, "leaderboard", redis.Z{Score: 1500, Member: "player_alice"})

// 2. Get Top 3
top3, _ := rdb.ZRevRange(ctx, "leaderboard", 0, 2).Result()

// 3. Get Rank
rank, _ := rdb.ZRevRank(ctx, "leaderboard", "player_alice").Result()