源码位置:t_zset.c/server.h
zset对象底层编码方式有两种,ziplist
或skiplist
。
使用ziplist编码需要同时满足以下两个条件:
- 有序集合对象中所有元素的大小都小于64字节。(可通过redis.conf配置:zset_max_ziplist_value)
- 有序集合对象保存的元素个数不超过128个。(可通过redis.conf配置:zset_max_ziplist_entries)
ziplist的结构如下:
如上图,集合的元素由两个紧挨着的节点来保存,第一个节点保存元素的成员,第二个节点保存元素的分值。压缩列表内的元素按照分值从小到大排序,分值小的靠近表头,分值大的靠近表尾。
zset编码底层实际上是由skiplist和dict构成的:
1 | typedef struct zset { |
为什么会使用两种数据结构呢?其实,使用单一的数据结构也是可以实现有序集合对象的,比如单独使用字典,查找时间复杂度为O(1),因为字典是无序的,所以当执行范围型操作时,首先要对所有元素进行排序,这里就会增加时间复杂度和空间复杂度了。当单独使用跳跃表时,查找的时间复杂度将会是O(logN)。所以,将两者的优势结合,将会很大的提高性能。另外,两种数据结构都会通过指针来共享相同的元素和分值,所以不会对内存造成不必要的浪费。
命令 | 功能 | 时间复杂度 |
---|---|---|
ZCARD | 返回key的有序集元素个数 | O(1) |
ZCOUNT | 返回有序集key中,score值在min和max之间(默认包括score值等于min或max)的成员 | O(log(N)) |
ZINCRBY | 为有序集key的成员member的score值加上增量increment | O(log(N)) |
ZINTERSTORE | 计算给定的numkeys个有序集合的交集,并且把结果放到destination中 | O(NK)+O(Mlog(M)),最坏的情况,N是最小的输入排序集,K是输入排序集的数量,M是结果排序集中的元素的数量 |
ZLEXCOUNT | 用于计算有序集合中指定成员之间的成员数量 | O(log(N)) |
ZPOPMAX | 删除并返回有序集合key中的最多count个具有最高得分的成员 | O(log(N)*M) |
ZPOPMIN | 删除并返回有序集合key中的最多count个具有最低得分的成员 | O(log(N)*M) |
ZRANGE | 返回存储在有序集合key中的指定范围的元素 | O(log(N)+M) |
ZRANGEBYLEX | 返回指定成员区间内的成员,按成员字典正序排序, 分数必须相同 | O(log(N)+M) |
ZREVRANGEBYLEX | 返回指定成员区间内的成员,按成员字典倒序排序, 分数必须相同 | O(log(N)+M) |
ZRANGEBYSCORE | 返回指定分数范围的元素列表 | O(log(N)+M) |
ZRANK | 返回有序集key中成员member的排名 | O(log(N)) |
ZREM | 在key集合中移除指定的元素 | O(M*log(N)) |
ZREMRANGEBYLEX | 删除名称按字典由低到高排序成员之间所有成员 | O(log(N)+M) |
ZREMRANGEBYRANK | 移除有序集key中,指定排名(rank)区间内的所有成员 | O(log(N)+M) |
ZREMRANGEBYSCORE | 移除有序集key中,所有score值介于min和max之间(包括等于min或max)的成员 | O(log(N)+M) |
ZREVRANGE | 返回有序集key中,指定区间内的成员 | O(log(N)+M) |
ZREVRANGEBYSCORE | 返回有序集合中指定分数区间内的成员,分数由高到低排序 | O(log(N)+M) |
ZREVRANK | 返回有序集key中成员member的排名,其中有序集成员按score值从大到小排列 | O(log(N)) |
ZSCORE | 返回有序集key中,成员member的score值 | O(1) |
ZUNIONSTORE | 计算给定的numkeys个有序集合的并集,并且把结果放到destination中 | O(N)+O(M log(M)) |
ZSCAN | 用于迭代集合类型中的集合成员 | O(1) |
函数功能总览
1 | void zaddCommand(client *c); |
Redis命令实现
添加命令:
1 | ZADD key [NX|XX] [CH] [INCR] score member [score member ...] |
代码:
1 | void zaddCommand(client *c) { |
其他命令:
1 | ZCARD key |