zset
Redis 中的 zset(Sorted Set,有序集合)是一种结合了 集合(Set) 和 有序列表(List) 特性的数据结构。它允许你存储一组唯一的成员(类似 Set),但每个成员会关联一个 分数(score)
,并根据分数对成员进行排序(类似 List)。这使得 zset 非常适合需要按特定顺序快速访问数据的场景。
适用于需要按特定顺序快速访问数据的场景。
注:
zset
的成员是唯一的, 但分数可以重复成员默认按分数升序排列(从小到大),也可以通过命令按降序访问。
支持快速插入、删除、范围查询和排名查询,时间复杂度通常为
O(log N)
。
分数的定义:
-
分数的数据类型为双精度浮点数的字符串类型。
-
+inf
和-inf
:正无穷(
-inf
) 和 负无穷(-inf
) 是合法值, 用于表示极端分数。+inf
: 成员会被排序到zset
的末尾。-inf
: 成员会被排序到zset
的开头。
-
若提供的
score
无法解析为合法浮点数, 则报错。
格式:
KEY: [zset_name]
VALUE:
member1 → score1
member2 → score2
...
底层实现
ziplist
(压缩列表): 当成员数量较少, 且占用内存少时使用, 可以有效节省内存。
- 成员数量 ≤
zset-max-ziplist-entries
(默认128
)。 - 成员值的字节大小 ≤
zset-max-ziplist-value
(默认64
字节)。 - 存储格式:
- 成员(member)和分数(score)交替存储,按分数升序排列。
skiplist
(跳跃表 + 哈希表): 当成员数量较多时使用, 跳跃表支持高校范围查询, 哈希表支持快速成员查找。
- 当成员数量或体积超过 ziplist 限制时,自动转换为跳跃表。
-
跳跃表(Skip List):
- 按分数排序,支持快速范围查询(如
ZRANGE
)。 - 每个节点包含成员和分数,并维护多层指针,实现
O(log N)
的查询效率。
- 按分数排序,支持快速范围查询(如
-
哈希表(Dict):
- 存储
member -> score
的映射,支持O(1)
时间复杂度的ZSCORE
操作。
- 存储
常用命令:
1. ZADD
向zset
中添加一个或多个成员,或更新已存在成员的分数score
。如果 key
不存在,则创建一个新的zset
。
语法:
ZADD key [NX | XX] [GT | LT] [CH] [INCR] score member [score member ...]
参数:
-
NX: 仅添加新成员, 不更新已存在的成员。
-
XX: 仅更新已存在成员, 不添加新成员
-
LT: 仅当新分数 < 当前分数时更新(默认覆盖旧分数)。
-
GT: 仅当新分数 > 当前分数时更新(默认覆盖旧分数)。
-
CH: 返回被修改成员的总数: 默认只返回新增成员数, 含新增的更新的成员数。
-
INCR: 递增模式: 将成员的分数增加到指定值(类似 ZINCRBY)。
- 注意: 此时只能指定一个 分数/成员对。
ZADD myzset INCR 7 "abc" # 若原分数为 1,则新分数为 8,返回 "8"
注:
NX
和XX
互斥,不能同时使用。
LT
和GT
互斥,不能同时使用。INCR
不能与其他选项(NX
、XX
、LT
、GT
)同时使用。
2. ZRANGE
返回 zset
中指定范围内的成员。支持按索引、分数或字典序(lexicographical order)查询,并可通过选项控制排序方向和返回格式。
语法:
ZRANGE key start stop [BYSCORE | BYLEX] [REV] [LIMIT offset count]
[WITHSCORES]
参数:
-
BYSCORE
: 按分数查询示例:
ZRANGE key 0 100 BYSCORE
返回分数在[0, 100]
的成员。 -
BYLEX
: 按字典序查询-
使用
[value
(包含)、(value
(不包含)指定范围。示例:
ZRANGE key [a [z BYLEX
返回字典序在a
到z
之间的成员。
-
-
LIMIT offset count
offset
:跳过的结果数量。count
:返回的最大结果数量。
-
WITHSCORES
: 返回成员和分数交替排列的列表。 -
REV
:按降序排列返回结果。
注意:
- 性能提示:超大范围查询(如
ZRANGE key 0 -1
)可能阻塞服务器,建议使用LIMIT
分页。- 字典序规则:基于成员的二进制字节值排序,区分大小写(如
"a"
<"A"
)。- 分数相同时的排序:若未指定
BYLEX
,相同分数成员按字典序升序排列。
3. ZSCORE
返回 zset
中指定成员关联的分数, 若成员不存在或键不存在,则返回 nil
。
语法:
ZSCORE key member
返回值:
- 如果成员存在:返回成员的分数(字符串形式)。
- 如果成员不存在或键不存在:返回
nil
。 - 如果键存在但不是有序集合类型:返回错误
(error) WRONGTYPE
。
4. ZCARD
用于获取zset
的成员总数。若 key
不存在则返回 0. 若 key
类型不为 zset
, 则返回报错WRONGTYPE
语法:
ZCARD key
5. ZREM
从zset
中删除一个或多个指定成员。若成员不存在,则忽略该成员;若key
不存在,则返回 0. 若 key
类型不为 zset
, 则返回报错WRONGTYPE
语法:
ZREM key member [member ...]
6. ZINCRBY
用于对zset
中指定成员的分数(score)进行增减操作,支持整数或浮点数增量。
语法:
ZINCRBY key increment member
特性:
动态更新分数:若成员存在,则直接修改其分数;若成员不存在,则自动添加并初始化分数
灵活增减: 通过正数增加分数,负数减少分数
例:
ZINCRBY key -5 member
原子性操作:保证在高并发场景下的数据一致性