Redis Sorted Sets (Part 1)

A sorted set is a set with scores, where elements are sorted by score. This lesson covers basic sorted set operations.

What is a Sorted Set?

Sorted set features:

leaderboard
├─ "player1" → score: 100
├─ "player2" → score: 200
├─ "player3" → score: 300
└─ "player4" → score: 400
💡 Internal implementation: Sorted sets use a skip list + hash table. The skip list supports efficient sorting and range queries, while the hash table enables fast score lookups.

ZADD: Add Elements

Basic Usage

REDIS
# Add a single element
ZADD leaderboard 100 "player1"
(integer) 1  # Returns number of newly added elements

# Add multiple elements
ZADD leaderboard 200 "player2" 300 "player3" 400 "player4"
(integer) 3

ZADD Parameters

REDIS
# NX: Only add new elements, don't update existing ones
ZADD leaderboard NX 150 "player1"
(integer) 0  # player1 already exists, not updated

# XX: Only update existing elements, don't add new ones
ZADD leaderboard XX 500 "player5"
(integer) 0  # player5 doesn't exist, not added

# CH: Return the number of changed elements (including updates)
ZADD leaderboard CH 120 "player1"
(integer) 1  # Updated player1's score

# INCR: Increment score (equivalent to ZINCRBY)
ZADD leaderboard INCR 50 "player1"
"170"  # Returns new score

Updating an Existing Element's Score

REDIS
# If element already exists, update its score
ZADD leaderboard 250 "player1"

# View new score
ZSCORE leaderboard "player1"
"250"

ZSCORE: Get Element Score

REDIS
ZADD leaderboard 100 "player1" 200 "player2"

# Get score
ZSCORE leaderboard "player1"
"100"

# Element does not exist
ZSCORE leaderboard "notexist"
(nil)

ZRANK and ZREVRANK: Get Rank

ZRANK: Rank from Low to High

REDIS
ZADD leaderboard 100 "player1" 200 "player2" 300 "player3"

# Rank starts at 0
ZRANK leaderboard "player1"
(integer) 0  # 1st place (lowest score)

ZRANK leaderboard "player2"
(integer) 1  # 2nd place

ZRANK leaderboard "player3"
(integer) 2  # 3rd place

ZREVRANK: Rank from High to Low

REDIS
# Rank from high to low (highest score is rank 0)
ZREVRANK leaderboard "player3"
(integer) 0  # 1st place (highest score)

ZREVRANK leaderboard "player2"
(integer) 1  # 2nd place

ZREVRANK leaderboard "player1"
(integer) 2  # 3rd place
💡 Rank rules:

  • ZRANK: low to high score, lowest score has rank 0
  • ZREVRANK: high to low score, highest score has rank 0
  • Rank starts at 0, 1st place has rank 0

ZRANGE and ZREVRANGE: Get Elements by Rank Range

ZRANGE: Get by Rank Range (Low to High)

REDIS
ZADD leaderboard 100 "player1" 200 "player2" 300 "player3" 400 "player4"

# Get all elements
ZRANGE leaderboard 0 -1
1) "player1"
2) "player2"
3) "player3"
4) "player4"

# Get first 2 elements
ZRANGE leaderboard 0 1
1) "player1"
2) "player2"

# Get last 2 elements
ZRANGE leaderboard -2 -1
1) "player3"
2) "player4"

# Get elements with scores
ZRANGE leaderboard 0 -1 WITHSCORES
1) "player1"
2) "100"
3) "player2"
4) "200"
5) "player3"
6) "300"
7) "player4"
8) "400"

ZREVRANGE: Get by Rank Range (High to Low)

REDIS
# Get all elements from high to low
ZREVRANGE leaderboard 0 -1 WITHSCORES
1) "player4"
2) "400"
3) "player3"
4) "300"
5) "player2"
6) "200"
7) "player1"
8) "100"

# Get top 3 (highest scores)
ZREVRANGE leaderboard 0 2 WITHSCORES
1) "player4"
2) "400"
3) "player3"
4) "300"
5) "player2"
6) "200"

ZCARD: Get Element Count

REDIS
ZADD leaderboard 100 "player1" 200 "player2" 300 "player3"

ZCARD leaderboard
(integer) 3

ZCOUNT: Count Elements Within a Score Range

REDIS
ZADD leaderboard 100 "player1" 150 "player2" 200 "player3" 250 "player4" 300 "player5"

# Count elements with scores between 150 and 250
ZCOUNT leaderboard 150 250
(integer) 3  # player2, player3, player4

# Use -inf and +inf for negative/positive infinity
ZCOUNT leaderboard -inf +inf
(integer) 5  # All elements

ZREM: Remove Elements

REDIS
ZADD leaderboard 100 "player1" 200 "player2" 300 "player3"

# Remove a single element
ZREM leaderboard "player1"
(integer) 1

# Remove multiple elements
ZREM leaderboard "player2" "player3"
(integer) 2

# Remove a non-existent element
ZREM leaderboard "notexist"
(integer) 0

ZINCRBY: Increment Score

REDIS
ZADD leaderboard 100 "player1"

# Increase score by 50
ZINCRBY leaderboard 50 "player1"
"150"  # Returns new score

# Decrease score (pass a negative number)
ZINCRBY leaderboard -20 "player1"
"130"

Sorted Set Use Cases

Use Case 1: Gaming Leaderboard

REDIS
# Update player scores
ZADD game:leaderboard 1500 "player:123"
ZADD game:leaderboard 2300 "player:456"
ZADD game:leaderboard 1800 "player:789"

# Get top 10
ZREVRANGE game:leaderboard 0 9 WITHSCORES

# Get player rank
ZREVRANK game:leaderboard "player:123"

# Increase player score
ZINCRBY game:leaderboard 100 "player:123"
REDIS
# Update trending heat scores
ZADD hot:search 10000 "Redis tutorial"
ZADD hot:search 8000 "Python basics"
ZADD hot:search 15000 "JavaScript"

# Get top 10 trending
ZREVRANGE hot:search 0 9 WITHSCORES

# Increase heat score
ZINCRBY hot:search 100 "Redis tutorial"

Use Case 3: Delayed Queue

REDIS
# Add delayed tasks (score is execution timestamp)
ZADD delay:queue 1719129600 "task:1"  # 2024-06-23 10:00:00
ZADD delay:queue 1719133200 "task:2"  # 2024-06-23 11:00:00

# Get tasks before current time (tasks to execute)
ZRANGEBYSCORE delay:queue -inf 1719129600

Use Case 4: Weighted Tags

REDIS
# User interest tags (score is interest level)
ZADD user:1:interests 100 "redis"
ZADD user:1:interests 80 "database"
ZADD user:1:interests 60 "cache"

# Get user's most interesting tags
ZREVRANGE user:1:interests 0 4 WITHSCORES

Use Case 5: Exam Rankings

REDIS
# Student scores
ZADD exam:math 95 "student:1"
ZADD exam:math 88 "student:2"
ZADD exam:math 92 "student:3"

# Get score ranking
ZREVRANGE exam:math 0 -1 WITHSCORES

# Get student rank
ZREVRANK exam:math "student:1"

Sorted Set Encoding Optimization

Redis automatically selects encoding based on sorted set size:

Encoding Condition Description
ziplist Elements <= 128, element length <= 64 bytes Compressed list, saves memory
skiplist Elements > 128 or element length > 64 bytes Skip list + hash table, better performance

Checking Encoding Type

REDIS
ZADD small:zset 1 "a" 2 "b" 3 "c"
OBJECT ENCODING small:zset
"ziplist"

# After adding many elements
OBJECT ENCODING large:zset
"skiplist"

❓ FAQ

Q What's the difference between a sorted set and a set?
A Every element in a sorted set has a score and is sorted by it. Sets are unordered. Sorted sets are ideal for leaderboards and ranking scenarios.
Q Can scores be decimals?
A Yes. Scores are double-precision floating-point numbers, supporting decimals.
Q Does ZRANK return ranks starting from 0 or 1?
A From 0. 1st place has rank 0, 2nd place has rank 1.
Q How do I get the element with the highest score?
A Use ZREVRANGE key 0 0 or ZRANGE key -1 -1.
Q Can elements be duplicated?
A No. Elements are unique, but scores can be duplicated.

📖 Summary

📝 Exercises

  1. Leaderboard: Use a sorted set to implement a gaming leaderboard — update scores, view ranks, get top 10
  2. Trending list: Implement a trending search list — update heat scores, view trending, increase heat
  3. Exam ranking: Store student scores in a sorted set, view rankings and scores
  4. Delayed queue: Use a sorted set to implement a delayed task queue — add tasks, get due tasks

Next Lesson

In the next lesson, we will learn Redis Sorted Sets (Part 2), covering advanced sorted set operations.

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏