一、zset数据结构
相比于set,sorted set 增加了一个权重参数 score,使得集合中的元素能够按 score 进行有序排列,还可以通过 score 的范围来获取元素的列表。
zset有两种不同的实现,分别是zipList和skipList。
zipList:
满足以下两个条件:
- [score,value]键值对数量少于128个;
- 每个元素的长度小于64字节;
skipList:
不满足以上两个条件时使用跳表(组合了hash和skipList)
- hash用来存储value到score的映射,这样就可以在O(1)时间内找到value对应的分数;
- skipList按照从小到大的顺序存储分数;
- skipList每个元素的值都是[score,value]对
二、Redis的zset
Redis 中 zset 不是单一结构完成,是跳表和哈希表共同完成。
实现方式:Redis sorted set的内部使用HashMap和跳跃表(skipList)来保证数据的存储和有序,HashMap里放的是成员到score的映射,而跳跃表里存放的是所有的成员,排序依据是HashMap里存的score,使用跳跃表的结构可以获得比较高的查找效率,并且在实现上比较简单。
使用zipList的示意图如下所示:
使用跳表时的示意图:
hash用于记录权重
ps:跳表介绍可以参考如下文章
Redis 跳跃表的原理和实现_redis跳表原理_击水三千里的博客-CSDN博客
三、详细操作
基础操作(zadd、zcrad、zcount)
127.0.0.1:6379> zadd books 49 java 79 springboot 80 python 50 php # 添加元素 (integer) 4 127.0.0.1:6379> zadd books 30 java2 (integer) 1 127.0.0.1:6379> zcard books # 查看数量 (integer) 5 127.0.0.1:6379> zcount books 0 3 # 根据分数显示指定的元素,有没有分数在 0 到 3 的数据,这里就返回 0 (integer) 0 127.0.0.1:6379> zcount books 0 70 # 返回分数在 0 到 70 之间的数据 (integer) 3 127.0.0.1:6379>
排序操作(zrange 、zrevrange )
127.0.0.1:6379>zrange books 0 -1 # 顺序查询集合中的成员 1) "java2" 2) "java" 3) "php" 4) "springboot" 5) "python" 127.0.0.1:6379> zrevrange books 0 -1 # 倒序查看集合中的成员 1) "python" 2) "springboot" 3) "php" 4) "java" 5) "java2" 127.0.0.1:6379>
根据分数显示元素(zrangebyscore)
这里有一个内置值 inf,表示无穷, -inf 表示负无穷, +inf 表示正无穷
127.0.0.1:6379> zrangebyscore books -inf +inf # 显示元素从大到小排序 1) "java2" 2) "java" 3) "php" 4) "springboot" 5) "python" 127.0.0.1:6379> zrangebyscore books -inf +inf withscores # 显示元素从大到小,并且附带成绩 1) "java2" 2) "30" 3) "java" 4) "49" 5) "php" 6) "50" 7) "springboot" 8) "79" 9) "python" 10) "80" 127.0.0.1:6379> zrangebyscore books -inf 50 withscores # 显示元素 <= 50 的那部分 1) "java2" 2) "30" 3) "java" 4) "49" 5) "php" 6) "50" 127.0.0.1:6379>
删除操作(zrem、zremrangebyrank、zremrangebyscore)
127.0.0.1:6379> zrem books java # 删除指定元素 (integer) 1 127.0.0.1:6379> zrange books 0 -1 1) "java2" 2) "php" 3) "springboot" 4) "python" 127.0.0.1:6379> zremrangebyrank books 0 -1 # 根据数组下标删除指定的元素 (integer) 4 127.0.0.1:6379> zrange books 0 -1 (empty list or set) 127.0.0.1:6379>
127.0.0.1:6379> zadd mysort 10 key1 20 key2 30 key3 40 key4 # 重新添加集合元素 (integer) 4 127.0.0.1:6379> zadd mysort 10 key5 30 key6 (integer) 2 127.0.0.1:6379> zrange mysort 0 -1 # 查看集合中的元素 1) "key1" 2) "key5" 3) "key2" 4) "key3" 5) "key6" 6) "key4" 127.0.0.1:6379> zremrangebyrank mysort 0 2 # 根据数组的下标来删除元素 (integer) 3 127.0.0.1:6379> zrange mysort 0 -1 1) "key3" 2) "key6" 3) "key4" 127.0.0.1:6379> zrangebyscore mysort -inf +inf WITHSCORES 1) "key3" 2) "30" 3) "key6" 4) "30" 5) "key4" 6) "40" 127.0.0.1:6379> zremrangebyscore mysort 0 1 # 根据分数来删除,但是此时没有分数满足 0 到 1 删除的结果就为 0 (integer) 0 127.0.0.1:6379> zrange mysort 0 -1 # 再次查看 1) "key3" 2) "key6" 3) "key4" 127.0.0.1:6379> zremrangebyscore mysort 0 35 # 再次根据分数来删除 (integer) 2 127.0.0.1:6379> zrange mysort 0 -1 1) "key4" 127.0.0.1:6379>