Redis 数据结构-zset
Redis 中的zset 结构, 是一个既类似于hash 又类似于set 还类似于list的一种特殊数据结构. zset 会根据元素的value 自动排序, 默认是升序.
- 类似于hash 是因为它里面的每个元素都是一个键值对, 只不过它的键值对有点儿特殊, value 必须是浮点数.
- 类似于set 是因为它里面的元素的field 不能重复
- 类似于list 是因为它是有顺序的, 排序规则为: 按照分值升序, 分值相同按名称升序
1. 常用命令
操作命令 | 描述 |
---|---|
zadd $key [NX / XX ] [CH] [INCR] score number [ score number…] | 添加成员到指定有序集合 |
zincrby $key $score $member | 调整成员的得分score |
zcard $key | 获取有序集合的元素个数 |
zcount k e y [ ( ] key [(] key[(]minScore [(]$maxScore; | 就算分值范围内的成员数量, 可灵活控制开闭区间. |
zlexcount $key ( | [$minmember ( |
zscore $key $member | 获取成员的得分. |
zrank/zrevrank $key $member | 获取成员的正向/逆向排名 |
zrange/zrevrange $key $start $end | 根据索引范围获取元素的升序或降序列表. |
zrem $key m e m b e r [ member [ member[member…] | 移除有序集合中的成员 |
zremrangebylex k e y [ key [ key[minmember [$maxmember; | 按成员名称排序删除两个成员直接的元素. | |
zremrangebyrank $key $start $stop | 按排名删除一区间内的所有元素 |
zrange $key $minIndex $maxIndex | 根据正向索引, 获取元素区间列表,可灵活控制开闭区间,无分页 |
zrevrange $key $minIndex $maxIndex | 根据逆向向索引, 获取元素区间列表,可灵活获取开闭区间,无分页 |
zrangebylex $key ( | [$minMember ( |
zrevrangebylex $key ( | [$maxMember ( |
Zrangebyscore k e y [ ( ] key [(] key[(]minScore [(]$maxScore | WITHSORES |
zrevrangebyscore k e y [ ( ] key [(] key[(]maxScore [(]$minScore | WITHSORES |
1.1 zadd
命令格式: zadd $key [NX | XX ] [CH | INCR] score number [ score number…]
- CH: 可选参数; zadd 命令默认返回有序集合中新增的成员数量, 添加CH 选项之后该命令将返回修改的成员数量.此参数和INCR共同使用时无效.
- NX: 可选参数; 不更新已存在的成员, 只新增不存在的成员. 返回值为新增成功的数量.
- XX: 可选参数; 更新已存在的成员, 不新增不存在的成员. 通常需要配合CH 选项来判断是否操作成功,因为默认一直返回0.
- INCR: 可选参数; 对成员的分值进行新增操作, 相当于zincrby 命令. 添加此参数后,命令不能再进行批量操作. 命令返回修改后的值
# 批量新增成员,返回新增成员的数量.如果原来存在则覆盖更新
127.0.0.1:6379> zadd dict 10 A 20 B
(integer) 2
127.0.0.1:6379> zrange dict 0 -1
1) "A"
2) "B"
# 由于A 已经存在, 所以对A的操作无效, 新增C成功. 但是从返回值并不能直接看出对A无效, 因为zadd命令默认返回新增的数量. 需要查看一下A的得分即可.
127.0.0.1:6379> zadd dict NX 30 A 40 C
(integer) 1
127.0.0.1:6379> zscore dict A
"10"
127.0.0.1:6379> zrange dict 0 -1
1) "A"
2) "B"
3) "C"
# 由于A存在原来的得分是10,现在修改为15,所以返回值加1; B 虽然存在,但是原来得分就是20,并未发生变化,所以返回值不加1; E原来并不存在, 所以返回值不加1
127.0.0.1:6379> zadd dict XX CH 15 A 20 B 30 E
(integer) 1
# 对已存在的成员做INCR,会在原来的score上增加
127.0.0.1:6379> zadd dict INCR 20 A
"35"
# 对不存在的成员做INCR,会新增成员,默认值为设置的score
127.0.0.1:6379> zadd dict INCR 10 E
"10"
127.0.0.1:6379> zrange dict 0 -1
1) "B"
2) "A"
3) "C"
1.2 zincrby
命令格式: zincrby $key $score $member; 调整成员的得分score
- 如果有序集合不存在,则自动创建有序集合; 如果成员不存在,则自动新增成员; 如果都存在,则原有的score 新增
- 返回新增后的score
- 不支持批量操作
127.0.0.1:6379> zincrby dict 10 A
"10"
127.0.0.1:6379> zincrby dict 10 A
"20"
1.3 zcard
命令格式: zcard $key; 获取有序集合的元素个数.
- 当有序集合存在时,返回有序集合中元素个数; 否则返回0;
#有序集合存在时,返回有序结合元素个数
127.0.0.1:6379> zadd dict 10 A 20 B 30 C 40 D 50 E
(integer) 5
127.0.0.1:6379> zcard dict
(integer) 5
#有序集合不存在,返回0
127.0.0.1:6379> zcard dict2
(integer) 0
1.4 zcount
命令格式: zcount k e y [ ( ] key [(] key[(]minScore [(]$maxScore; 就算分值范围内的成员数量, 可灵活控制开闭区间.
- 当有序集合不存在时,返回0; 否则返回区间范围内成员数量
- 默认的区间范围是全闭合区间, 可通过添加(来设置开区间
- 特殊符号 -inf 表示有序集合中成员的最小得分
- 特殊符号 +inf 表示有序集合中成员的最大得分
# 初始化有序集合
127.0.0.1:6379> zadd dict 10 A 20 B 30 C 40 D 50 E 60 F
(integer) 6
# 计算 10 <= score <= 50 的成员个数
127.0.0.1:6379> zcount dict 10 50
(integer) 5
# 计算 10 < score <= 50 的成员个数
127.0.0.1:6379> zcount dict (10 50
(integer) 4
# 计算 score<=30 的成员个数
127.0.0.1:6379> zcount dict -inf 30
(integer) 3
# 计算 score > 30 的成员个数
127.0.0.1:6379> zcount dict (30 +inf
(integer) 3
# 计算所有成员个数
127.0.0.1:6379> zcount dict -inf +inf
(integer) 6
# 当有序集合不存在时返回0
127.0.0.1:6379> zcount dict2 -inf +inf
(integer) 0
1.5 zlexcount
命令格式: zlexcount k e y ( ∣ [ key (|[ key(∣[minmember (|[$maxmember; 获取两个成员之间的成员数量, 一定程度上可灵活控制开闭区间.
- 当有序集合不存在时, 返回0; 否则返回区间范围内成员数量
- 参数为成员名称,而非成员得分. 成员名称必须结合开闭区间符号使用
- 特殊符号 – 表示最小得分的成员
- 特殊符号 + 表示最大得分的成员
- 遗憾的是特殊符号±不能与开区间结合使用, 因此涉及到± 符号的都是包含最大得分成员或包含最小得分成员的结果
# 初始化dict
127.0.0.1:6379> zadd dict 10 A 20 B 30 C 40 D 50 E 60 F
(integer) 5
# 计算 A <= score <= E 的元素个数, 即成员A 和 成员E 之间的元素个数, 包含A 和 E
127.0.0.1:6379> zlexcount dict [A [E
(integer) 5
# 计算 A < score <= E 的元素个数, 即成员A 和 成员 E 之间的成员个数, 包含E,不包含A
127.0.0.1:6379> zlexcount dict (A [E
(integer) 4
# 计算 score <=C 的成员个数, 即排在成员C之前的成员个数, 包含C
127.0.0.1:6379> zlexcount dict - [C
(integer) 3
# 计算score >C 的成员个数, 即排在成员C之后的成员个数, 不包含C
127.0.0.1:6379> zlexcount dict (C +
(integer) 3
# 计算所有成员个数
127.0.0.1:6379> zlexcount dict - +
(integer) 6
#对于特殊符号+ -, 不能结合使用开区间符号
127.0.0.1:6379> zlexcount dict (- (+
(integer) 0
1.6 zscore
命令格式: zscore $key $member; 获取成员的得分.
- 成员不存在返回nil, 否则返回成员的浮点数得分, 以字符串表示
- 不支持批量操作
# 成员存在返回成员得分
127.0.0.1:6379> zscore dict A
"35"
# 有序集合或成员不存在返回nil
127.0.0.1:6379> zscore dict -A
(nil)
127.0.0.1:6379> zscore dict2 A
(nil)
1.7 zrank/zrevrank
命令格式: zrank/zrevrank $key $member; 获取成员的正向/逆向排名
- zrank返回成员score从小到大的排名, zrevrank返回成员score 从大到小的排名
- 当有序集合不存在或成员不存在时,返回nil
# 初始化dict
127.0.0.1:6379> zadd dict 10 A 20 B 30 C 40 D 50 E
(integer) 5
# 获取成员的正向排名
127.0.0.1:6379> zrank dict D
(integer) 3
# 获取成员的逆向排名
127.0.0.1:6379> zrevrank dict D
(integer) 1
# 当有序集合或成员不存在时,返回nil
127.0.0.1:6379> zrank dict f
(nil)
127.0.0.1:6379> zrank dict2 f
(nil)
1.8 zrange
命令格式: zrange $key $minIndex $maxIndex ; 根据索引升序, 获取元素区间列表列表.
- 索引可以为正负数, 正负数只表示索引的方向.
- 索引0 表示最左边第一个元素, 索引-1表示最右边第一个元素
- 当有序集合不存在或有序集合为空时,返回空的列表
- 默认只返回成员名称, 可使用withscores 同时返回成员得分. 但是返回的依然是列表,只是列表长度是只返回成员名称的两倍.
# 初始化有序集合
127.0.0.1:6379> zadd dict 10 A 20 B 30 C 40 D
(integer) 4
# 获取有序集合中所有元素, 获得score的升序列表
127.0.0.1:6379> zrange dict 0 -1
1) "A"
2) "B"
3) "C"
4) "D"
5) "E"
# 降序列表,获得score的降序列表
127.0.0.1:6379> zrange dict 0 2
1) "A"
2) "B"
3) "C"
# 获取有序集合中得分最靠后的两个元素
127.0.0.1:6379> zrange dict -3 -2
1) "C"
2) "D"
# 返回成员名称的同时返回成员得分
127.0.0.1:6379> zrange dict 0 1 withscores
1) "A"
2) "10"
3) "B"
4) "20"
# 当有序集合不存在时返回空的列表
127.0.0.1:6379> zrange dict2 0 -1
(empty list or set)
1.9 zrevrange
命令格式: zrevrange $key $minIndex $maxIndex ; 根据索引升序, 获取元素区间列表列表.
- zrevrange 和 zrevrange 唯一的区别返回结果一个是升序列表,一个是降序列表
- 索引可以为正负数, 正负数只表示索引的方向.
- 索引0 表示最左边第一个元素, 索引-1表示最右边第一个元素
- 当有序集合不存在或有序集合为空时,返回空的列表
- 默认只返回成员名称, 可使用withscores 同时返回成员得分. 但是返回的依然是列表,只是列表长度是只返回成员名称的两倍.
# 初始化有序集合
127.0.0.1:6379> zadd dict 10 A 20 B 30 C 40 D
(integer) 4
# 获取有序集合中所有元素, 获得score的升序列表
127.0.0.1:6379> zrevrange dict 0 -1
1) "E"
2) "D"
3) "C"
4) "B"
5) "A"
# 降序列表,获得score的降序列表
127.0.0.1:6379> zrevrange dict 0 2
1) "E"
2) "D"
3) "C"
# 获取有序集合中得分最靠后的两个元素
127.0.0.1:6379> zrevrange dict -3 -2
1) "C"
2) "B"
# 返回成员名称的同时返回成员得分
127.0.0.1:6379> zrevrange dict 0 1 withscores
1) "E"
2) "50"
3) "D"
4) "40"
# 当有序集合不存在时返回空的列表
127.0.0.1:6379> zrange dict2 0 -1
(empty list or set)
1.9 zrangebylex
命令格式: zrangebylex k e y ( ∣ [ key (|[ key(∣[minMember (|[$maxMember [limit $offset $count]; 对成员名称采用字符串升序排序方式获取区间元素.
- 所有成员得分必须相同, 否则结果可能不正确. 因为只有得分相同, 存储顺序才会按照成员名称的字符串顺序排列.
- 成员必须使用开闭区间限制返回列表中是否包含边缘成员
- 特殊符号 + 表示字符串排名最后的成员,不能结合开闭区间符号使用
- 特殊符号 – 表示字符串排名最前的成员,不能结合开闭区间符号使用
- 可用limit 实现分页, 分页方式和mysql 分页方式极其相似
- 当成员不存在或给定区间之间没有元素时,返回空列表
# 初始化有序集合
127.0.0.1:6379> zadd dict 0 A 0 B 0 C 0 D 0 E 0 F
(integer) 6
# 按字符串升序, 获取 B <= member <= D 的成员列表, 即获取成员B 和 成员D之间的所有成员, 区间左闭右闭
127.0.0.1:6379> zrangebylex dict [B [D
1) "B"
2) "C"
3) "D"
# 按字符串升序, 获取 B < member <= D 的成员列表, 即获取成员B 和 成员D之间的所有成员, 区间左开右闭
127.0.0.1:6379> zrangebylex dict (B [D
1) "C"
2) "D"
# 按字符串升序, 获取成员 member >= D 的成员列表, 即获取成员B之后的所有成员, 包含B和最后一个成员
127.0.0.1:6379> zrangebylex dict [D +
1) "D"
2) "E"
3) "F"
# 模拟分页: 获取第一页数据,每页成员个数为2
127.0.0.1:6379> zrangebylex dict - + limit 0 2
1) "A"
2) "B"
# 模拟分页: 获取第二页数据,每页成员个数为2
127.0.0.1:6379> zrangebylex dict - + limit 2 2
1) "C"
2) "D"
# 当成员不存在或给定区间之间没有元素时,返回空列表
127.0.0.1:6379> zrangebylex dict + -
(empty list or set)
1.10 zrevrangebylex
命令格式: zrevrangebylex k e y ( ∣ [ key (|[ key(∣[maxMember (|[$minMember [limit $offset $count]; 对成员名称采用字符串降序排序方式获取区间元素.
- zrevrangebylex 和 zrangebylex 唯一的区别是minxmember 和 minmember 的位置不一样, 返回结果一个是升序列表,一个是降序列表
- 所有成员得分必须相同, 否则结果可能不正确. 因为只有得分相同, 存储顺序才会按照成员名称的字符串顺序排列.
- 成员必须使用开闭区间限制返回列表中是否包含边缘成员
- 特殊符号 + 表示字符串排名最后的成员,不能结合开闭区间符号使用
- 特殊符号 – 表示字符串排名最前的成员,不能结合开闭区间符号使用
- 可用limit 实现分页, 分页方式和mysql 分页方式极其相似
- 当成员不存在或给定区间之间没有元素时,返回空列表
# 初始化有序集合
127.0.0.1:6379> zadd dict 0 A 0 B 0 C 0 D 0 E 0 F
(integer) 6
# 按字符串降序, 获取 B <= member <= D 的成员列表, 即获取成员B 和 成员D之间的所有成员, 区间左闭右闭
127.0.0.1:6379> zrevrangebylex dict [D [B
1) "D"
2) "C"
3) "B"
# 按字符串降序, 获取 B < member <= D 的成员列表, 即获取成员B 和 成员D之间的所有成员, 区间左开右闭
127.0.0.1:6379> zrevrangebylex dict [D (B
1) "D"
2) "C"
# 按字符串降序, 获取成员 member >= D 的成员列表, 即获取成员B之后的所有成员, 包含B和最后一个成员
127.0.0.1:6379> zrevrangebylex dict + [D
1) "F"
2) "E"
3) "D"
# 模拟分页: 获取第一页数据,每页成员个数为2
127.0.0.1:6379> zrevrangebylex dict + - limit 0 2
1) "F"
2) "E"
# 模拟分页: 获取第二页数据,每页成员个数为2
127.0.0.1:6379> zrevrangebylex dict + - limit 2 2
1) "D"
2) "C"
# 当成员不存在或给定区间之间没有元素时,返回空列表
127.0.0.1:6379> zrangebylex dict + -
(empty list or set)
1.10 zrangebyscore
命令格式: zrangebyscore k e y [ ( ] key [(] key[(]minScore [(]$maxScore |WITHSORES| [limit $offset $count ]; 按成员得分升序, 获取得分区间的成员列表.可灵活控制开闭区间, 分页,返回得分.
- 参数得分默认为闭区间, 可使用开区间符号设置开区间
- 特殊符号 -inf 表示有序集合中最小得分
- 特殊符号 +inf 表示有序集合中最大得分
- 可用limit 实现分页, 分页方式和mysql 分页方式极其相似
- 默认返回列表只包含成员名称,可使用withscores 参数同时返回成员得分. 不过返回的依然是一个列表,列表大小为只有名称的2倍
# 初始化有序集合
127.0.0.1:6379> zadd dict 10 A 20 B 30 C 40 D 50 E
(integer) 5
# 按得分升序排序: 获取 10 <= score <=30 的成员列表, 区间左闭右闭
127.0.0.1:6379> zrangebyscore dict 10 30
1) "A"
2) "B"
3) "C"
# 按得分升序排序: 获取 10 < score < 30 的成员列表, 区间左开右开
127.0.0.1:6379> zrangebyscore dict (10 (30
1) "B"
# 按得分升序排序: 获取 score <= 30 的成员列表, 区间左闭右闭
127.0.0.1:6379> zrangebyscore dict -inf 30
1) "A"
2) "B"
3) "C"
# 按得分升序排序: 获取 score > 30 的成员列表, 区间左开右闭
127.0.0.1:6379> zrangebyscore dict (30 +inf
1) "D"
2) "E"
# 按得分升序排序: 对全部元素进行分页获取数据
127.0.0.1:6379> zrangebyscore dict -inf +inf limit 0 2
1) "A"
2) "B"
# 按得分升序排序: 分页获取数据, 返回成员名称的同时返回成员得分
127.0.0.1:6379> zrangebyscore dict -inf +inf withscores limit 0 2
1) "A"
2) "10"
3) "B"
4) "20"
1.10 zrevrangebyscore
命令格式: zrevrangebyscore k e y [ ( ] key [(] key[(]maxScore [(]$minScore |WITHSORES| [limit $offset $count ]; 按成员得分升序, 获取得分区间的成员列表.可灵活控制开闭区间, 分页,返回得分.
- zrangebyscore 和 zrevrangebyscore 唯一的区别是minxmember 和 minmember 的位置不一样, 返回结果一个是升序列表,一个是降序列表
- 参数得分默认为闭区间, 可使用开区间符号设置开区间
- 特殊符号 -inf 表示有序集合中最小得分
- 特殊符号 +inf 表示有序集合中最大得分
- 可用limit 实现分页, 分页方式和mysql 分页方式极其相似
- 默认返回列表只包含成员名称,可使用withscores 参数同时返回成员得分. 不过返回的依然是一个列表,列表大小为只有名称的2倍
# 初始化有序集合
127.0.0.1:6379> zadd dict 10 A 20 B 30 C 40 D 50 E
(integer) 5
# 按得分降序排序: 获取 10 <= score <=30 的成员列表, 区间左闭右闭
127.0.0.1:6379> zrevrangebyscore dict 30 10
1) "C"
2) "B"
3) "A"
# 按得分降序排序: 获取 10 < score < 30 的成员列表, 区间左开右开
127.0.0.1:6379> zrevrangebyscore dict (30 (10
1) "B"
# 按得分降序排序: 获取 score <= 30 的成员列表, 区间左闭右闭
127.0.0.1:6379> zrevrangebyscore dict 30 -inf
1) "C"
2) "B"
3) "A"
# 按得分降序排序: 获取 score > 30 的成员列表, 区间左开右闭
127.0.0.1:6379> zrevrangebyscore dict +inf (30
1) "E"
2) "D"
# 按得分降序排序: 对全部元素进行分页获取数据
127.0.0.1:6379> zrevrangebyscore dict +inf -inf limit 0 2
1) "E"
2) "D"
# 按得分降序排序: 分页获取数据, 返回成员名称的同时返回成员得分
127.0.0.1:6379> zrevrangebyscore dict +inf -inf withscores limit 0 2
1) "E"
2) "50"
3) "D"
4) "40"
1.11 zrem
命令格式: zrem $key m e m b e r [ member [ member[member…]; 移除有序集合中的成员
#初始化有序列表
127.0.0.1:6379> zadd dict 10 A 20 B 30 C 40 D 50 E
(integer) 5
# 批量删除有序集合中的成员, 因为不存在成员F, 所以返回4
127.0.0.1:6379> zrem dict A B C D F
(integer) 4
127.0.0.1:6379> zrange dict 0 -1
1) "E"
1.12 zremrangebylex
命令格式: zremrangebylex k e y [ key [ key[minmember [$maxmember; 按成员名称排序删除两个成员直接的元素.
- 成员之间的分值必须相同, 因为只有分值相同之后有序集合才会按成员名称进行排序
- 表示比最小的分值要小的成员, + 表示比最大分值大的成员
- ( 表示不闭合, 不包含 [表示闭合,包含
- 返回删除成员的数量
127.0.0.1:6379> zadd dict 0 A 0 Aa 0 Aaa 0 B 0 Bb 0 Bbb 0 C 0 Cc 0 Ccc
(integer) 9
# 删除成员A 和成员C 之间的元素
127.0.0.1:6379> zremrangebylex dict [A [C
(integer) 7
127.0.0.1:6379> zrange dict 0 -1
1) "Cc"
2) "Ccc"
# 删除所有的元素
127.0.0.1:6379> zremrangebylex dict - +
(integer) 2
127.0.0.1:6379> zrange dict 0 -1
(empty list or set)
1.13 zremrangebyrank
命令格式: zremrangebyrank $key $start $stop; 按排名删除一区间内的所有元素
- 返回删除元素的个数
- 区间范围为左闭右闭的区间
# 初始化dict
127.0.0.1:6379> zadd dict 10 A 20 B 30 C 40 D 50 E
(integer) 5
# 按排名删除排名为第二第三的成员
127.0.0.1:6379> zremrangebyrank dict 1 2
(integer) 2
127.0.0.1:6379> zrange dict 0 -1
1) "A"
2) "D"
3) "E"
# 删除排名倒数第二第三的成员
127.0.0.1:6379> zremrangebyrank dict -2 -1
(integer) 2
127.0.0.1:6379> zrange dict 0 -1
1) "A"
1.14 zremrangebyscore
zinterstore
zunionstore
相关命令
ZSCAN