Redis Sorted Sets (Part 2)

This lesson covers advanced sorted set features such as score-range queries and set operations.

ZRANGEBYSCORE: Query by Score Range

ZRANGEBYSCORE retrieves elements based on a score range.

Basic Usage

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

# Get elements with scores between 150 and 250
ZRANGEBYSCORE leaderboard 150 250
1) "player2"
2) "player3"
3) "player4"

# Get elements with scores
ZRANGEBYSCORE leaderboard 150 250 WITHSCORES
1) "player2"
2) "150"
3) "player3"
4) "200"
5) "player4"
6) "250"

Using -inf and +inf

REDIS
# Get elements with score <= 200
ZRANGEBYSCORE leaderboard -inf 200
1) "player1"
2) "player2"
3) "player3"

# Get elements with score >= 200
ZRANGEBYSCORE leaderboard 200 +inf
1) "player3"
2) "player4"
3) "player5"

# Get all elements
ZRANGEBYSCORE leaderboard -inf +inf

Open and Closed Intervals

REDIS
# Default is closed interval [150, 250]
ZRANGEBYSCORE leaderboard 150 250

# Open interval (150, 250) — excludes 150 and 250
ZRANGEBYSCORE leaderboard (150 (250

# Half-open [150, 250)
ZRANGEBYSCORE leaderboard 150 (250

# Half-open (150, 250]
ZRANGEBYSCORE leaderboard (150 250
💡 Syntax: Use parentheses ( to indicate an open interval (exclusive), no parentheses for a closed interval (inclusive).

LIMIT Pagination

REDIS
# Get elements scored 100-300, starting from index 1, take 2
ZRANGEBYSCORE leaderboard 100 300 LIMIT 1 2
1) "player2"
2) "player3"

ZREVRANGEBYSCORE: Query by Score Range (High to Low)

REDIS
# Get elements scored 150-250, from high to low
ZREVRANGEBYSCORE leaderboard 250 150 WITHSCORES
1) "player4"
2) "250"
3) "player3"
4) "200"
5) "player2"
6) "150"
⚠️ Note: The score range in ZREVRANGEBYSCORE goes from highest to lowest (250 150), not low to high.

ZRANGEBYLEX: Query by Lexicographical Order

When all elements have the same score, you can query by lexicographical (alphabetical) order.

Basic Usage

REDIS
# All elements have score 0
ZADD myzset 0 "apple" 0 "banana" 0 "cherry" 0 "date"

# Get all elements in lexicographical order
ZRANGEBYLEX myzset - +
1) "apple"
2) "banana"
3) "cherry"
4) "date"

# Get elements in lexicographical range [banana, cherry]
ZRANGEBYLEX myzset [banana [cherry
1) "banana"
2) "cherry"

# Get elements starting with "b"
ZRANGEBYLEX myzset [b (c
1) "banana"
💡 Use case: ZRANGEBYLEX is ideal for implementing autocomplete and dictionary lookups.

ZREMRANGEBYRANK: Remove by Rank Range

REDIS
ZADD leaderboard 100 "p1" 150 "p2" 200 "p3" 250 "p4" 300 "p5"

# Remove elements with rank 0 to 1 (lowest 2 scores)
ZREMRANGEBYRANK leaderboard 0 1
(integer) 2

ZRANGE leaderboard 0 -1
1) "p3"
2) "p4"
3) "p5"

ZREMRANGEBYSCORE: Remove by Score Range

REDIS
ZADD leaderboard 100 "p1" 150 "p2" 200 "p3" 250 "p4" 300 "p5"

# Remove elements with scores between 100 and 200
ZREMRANGEBYSCORE leaderboard 100 200
(integer) 3

ZRANGE leaderboard 0 -1 WITHSCORES
1) "p4"
2) "250"
3) "p5"
4) "300"

Use Case: Clean Up Expired Data

REDIS
# Delayed queue (score is timestamp)
ZADD delay:queue 1719129600 "task:1"
ZADD delay:queue 1719133200 "task:2"

# Remove completed tasks (timestamp less than current time)
ZREMRANGEBYSCORE delay:queue -inf 1719129600

ZREMRANGEBYLEX: Remove by Lexicographical Range

REDIS
ZADD myzset 0 "apple" 0 "banana" 0 "cherry" 0 "date"

# Remove elements in lexicographical range [banana, cherry]
ZREMRANGEBYLEX myzset [banana [cherry
(integer) 2

ZRANGE myzset 0 -1
1) "apple"
2) "date"

Sorted Set Operations

ZUNIONSTORE: Union

REDIS
# Create two sorted sets
ZADD zset1 1 "a" 2 "b" 3 "c"
ZADD zset2 4 "b" 5 "c" 6 "d"

# Calculate union (default: sum scores)
ZUNIONSTORE result 2 zset1 zset2
(integer) 4

ZRANGE result 0 -1 WITHSCORES
1) "a"
2) "1"
3) "d"
4) "6"
5) "b"
6) "6"   # 2 + 4
7) "c"
8) "8"   # 3 + 5

ZUNIONSTORE with Weights

REDIS
# Set weights
ZUNIONSTORE result 2 zset1 zset2 WEIGHTS 2 3
# zset1 scores multiplied by 2, zset2 scores multiplied by 3

ZRANGE result 0 -1 WITHSCORES
1) "a"
2) "2"   # 1 * 2
3) "d"
4) "18"  # 6 * 3
5) "b"
6) "16"  # 2*2 + 4*3
7) "c"
8) "21"  # 3*2 + 5*3

ZUNIONSTORE Aggregate Functions

REDIS
# Use MIN aggregate (take the minimum score)
ZUNIONSTORE result 2 zset1 zset2 AGGREGATE MIN

# Use MAX aggregate (take the maximum score)
ZUNIONSTORE result 2 zset1 zset2 AGGREGATE MAX

# Use SUM aggregate (sum, default)
ZUNIONSTORE result 2 zset1 zset2 AGGREGATE SUM

ZINTERSTORE: Intersection

REDIS
ZADD zset1 1 "a" 2 "b" 3 "c"
ZADD zset2 4 "b" 5 "c" 6 "d"

# Calculate intersection
ZINTERSTORE result 2 zset1 zset2
(integer) 2

ZRANGE result 0 -1 WITHSCORES
1) "b"
2) "6"   # 2 + 4
3) "c"
4) "8"   # 3 + 5

ZDIFFSTORE: Difference (Redis 6.2+)

REDIS
ZADD zset1 1 "a" 2 "b" 3 "c"
ZADD zset2 4 "b" 5 "c" 6 "d"

# Calculate difference
ZDIFFSTORE result 2 zset1 zset2
(integer) 1

ZRANGE result 0 -1 WITHSCORES
1) "a"
2) "1"

ZMSCORE: Batch Get Scores (Redis 6.2+)

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

ZMSCORE leaderboard "player1" "player2" "player4"
1) "100"
2) "200"
3) (nil)  # player4 does not exist

ZPOPMAX and ZPOPMIN: Pop Highest/Lowest Score Elements

ZPOPMAX: Pop the Highest-Scoring Element

REDIS
ZADD leaderboard 100 "p1" 200 "p2" 300 "p3"

# Pop the highest-scoring element
ZPOPMAX leaderboard
1) "p3"
2) "300"

# Pop 2 highest-scoring elements
ZPOPMAX leaderboard 2
1) "p2"
2) "200"
3) "p1"
4) "100"

ZPOPMIN: Pop the Lowest-Scoring Element

REDIS
ZADD leaderboard 100 "p1" 200 "p2" 300 "p3"

ZPOPMIN leaderboard
1) "p1"
2) "100"

BZPOPMAX and BZPOPMIN: Blocking Pop

REDIS
# If the sorted set is empty, block and wait up to 10 seconds
BZPOPMAX leaderboard 10

# Listen on multiple sorted sets
BZPOPMAX zset1 zset2 zset3 10
💡 Use case: BZPOPMAX/BZPOPMIN can be used to implement priority queues.

Advanced Sorted Set Applications

Use Case 1: Sliding Window Rate Limiting

REDIS
# Record user request timestamps
ZADD ratelimit:user:1 1719129600 "req1"
ZADD ratelimit:user:1 1719129605 "req2"
ZADD ratelimit:user:1 1719129610 "req3"

# Count requests in the last 60 seconds
ZCOUNT ratelimit:user:1 1719129540 1719129600

# Clean up requests older than 60 seconds
ZREMRANGEBYSCORE ratelimit:user:1 -inf 1719129540

Use Case 2: Autocomplete

REDIS
# All words with score 0
ZADD autocomplete 0 "apple" 0 "application" 0 "appetite" 0 "banana"

# Query words starting with "app"
ZRANGEBYLEX autocomplete [app [app\xff
1) "apple"
2) "application"
3) "appetite"

Use Case 3: Timeline

REDIS
# User timeline (score is timestamp)
ZADD timeline:user:1 1719129600 "post:1"
ZADD timeline:user:1 1719129605 "post:2"
ZADD timeline:user:1 1719129610 "post:3"

# Get the latest 10 posts
ZREVRANGE timeline:user:1 0 9

# Get posts within a time range
ZRANGEBYSCORE timeline:user:1 1719129600 1719129610

Use Case 4: Multi-Dimensional Ranking

REDIS
# Product sales ranking
ZADD sales:rank 1000 "product:1"
ZADD sales:rank 2000 "product:2"

# Product rating ranking
ZADD rating:rank 4.5 "product:1"
ZADD rating:rank 4.8 "product:2"

# Combined ranking (sales weight 0.6, rating weight 0.4)
ZUNIONSTORE combined:rank 2 sales:rank rating:rank WEIGHTS 0.6 0.4

❓ FAQ

Q What's the difference between ZRANGEBYSCORE and ZRANGE?
A ZRANGE queries by rank range; ZRANGEBYSCORE queries by score range.
Q How do I get the top N elements by score?
A Use ZREVRANGE key 0 N-1 WITHSCORES.
Q How do weights work in ZUNIONSTORE?
A Weights are multipliers. WEIGHTS 2 3 means multiply scores in the first set by 2 and the second set by 3.
Q Does ZRANGEBYLEX require all elements to have the same score?
A Yes. ZRANGEBYLEX assumes all elements have the same score and sorts them lexicographically.
Q How do I implement a priority queue?
A Use ZADD to add tasks (score = priority), and ZPOPMIN to pop the highest-priority task.

📖 Summary

📝 Exercises

  1. Score range query: Use ZRANGEBYSCORE to query elements in different score ranges
  2. Range deletion: Use ZREMRANGEBYSCORE to clean up expired data
  3. Set operations: Use ZUNIONSTORE to merge multiple leaderboards with different weights
  4. Sliding window: Use a sorted set to implement sliding window rate limiting

Next Lesson

In the next lesson, we will learn Redis HyperLogLog, covering cardinality estimation.

100%

🙏 帮我们做得更好

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

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