Redis中有序集合的内部实现方式的详细介绍


Posted in Redis onMarch 16, 2022

面试官:Redis中基本的数据类型有哪些?

我:Redis的基本数据类型有:字符串(string)、哈希(hash)、列表(list)、集合(set)、有序集合(zset)。

面试官:有序集合的内部实现方式是什么?

我还沉浸在上一个问题的沾沾自喜中,顿时表情凝固了,手心开始冒出冷汗。“这个。。没有太深入了解”,我支支吾吾的说到。

面试官:回去等消息吧。

这句话说的干净利落,然后就没有然后了。失败是成功的妈妈,我不气馁,决定马上恶补一下。

有序集合的内部实现

有序集合的内部实现有两种,分别是:压缩列表(ziplist)和跳跃表(skiplist)。接下来,我们分别进行详细的了解。

以压缩列表作为内部实现

当有序集合的元素个数小于zset-max-ziplist-entries(默认为128个),并且每个元素成员的长度小于zset-max-ziplist-value(默认为64字节)的时候,使用压缩列表作为有序集合的内部实现。

每个集合元素由两个紧挨在一起的两个压缩列表结点组成,其中第一个结点保存元素的成员,第二个结点保存元素的分支。压缩列表中的元素按照分数从小到大依次紧挨着排列,有效减少了内存空间的使用。

举个例子,我们使用zadd命令创建一个以压缩列表为实现的有序集合:

127.0.0.1:6379> zadd one-more-zset 1 one 2 two 3 three
(integer) 3
127.0.0.1:6379> zrange one-more-zset 0 -1
1) "one"
2) "two"
3) "three"
127.0.0.1:6379> object encoding one-more-zset
"ziplist"

以跳跃表作为内部实现

当有序集合的元素个数大于等于zset-max-ziplist-entries(默认为128个),或者每个元素成员的长度大于等于zset-max-ziplist-value(默认为64字节)的时候,使用跳跃表作为有序集合的内部实现。

此时,在有序集合中其实包含了两个结构,一个是跳跃表,另一个是哈希表。

在跳跃表中,所有元素按照从小到大的顺序排列。跳跃表的结点中的object指针指向元素成员的字符串对象,score保存了元素的分数。通过跳跃表,Redis可以快速地对有序集合进行分数范围、排名等操作。

在哈希表中,为有序集合创建了一个从元素成员到元素分数的映射。键值对中的键指向元素成员的字符串对象,键值对中的值保存了元素的分数。通过哈希表,Redis可以快速查找指定元素的分数。

虽然有序集合同时使用跳跃表和哈希表,但是这两种数据结构都使用指针共享元素中的成员和分数,不会额外的内存浪费。

举个例子,我们使用zadd命令创建一个以跳跃表为实现的有序集合:

127.0.0.1:6379> zadd one-more-zset 1 long-long-long-long-long-long-long-long-long-long-long-long-long-long
(integer) 1
127.0.0.1:6379> zrange one-more-zset 0 -1
1) "long-long-long-long-long-long-long-long-long-long-long-long-long-long"
127.0.0.1:6379> object encoding one-more-zset
"skiplist"

内部实现的转换

当一个有序集合是以压缩列表作为内部实现时,再向这个有序集合添加较长的元素成员,或向这个有序集合的元素个数过多时,那么这个有序集合就会转换为以跳跃表作为内部实现。但是,以跳跃表作为内部实现的有序集合不会转换为以压缩列表作为内部实现。

举个例子,我们先创建一个以压缩列表作为内部实现的有序集合:

127.0.0.1:6379> zadd one-more-zset 1 one 2 two 3 three
(integer) 3
127.0.0.1:6379> zrange one-more-zset 0 -1
1) "one"
2) "two"
3) "three"
127.0.0.1:6379> object encoding one-more-zset
"ziplist"

然后,再向它添加一个较长成员的元素,它就是转换为以跳跃表作为内部实现:

127.0.0.1:6379> zadd one-more-zset 4 long-long-long-long-long-long-long-long-long-long-long-long-long-long
(integer) 1
127.0.0.1:6379> zrange one-more-zset 0 -1
1) "one"
2) "two"
3) "three"
4) "long-long-long-long-long-long-long-long-long-long-long-long-long-long"
127.0.0.1:6379> object encoding one-more-zset
"skiplist"

然后,再把那一个较长成员的元素从有序集合中移除,有序集合依然是以跳跃表作为内部实现:

127.0.0.1:6379> zrem one-more-zset long-long-long-long-long-long-long-long-long-long-long-long-long-long
(integer) 1
127.0.0.1:6379> zrange one-more-zset 0 -1
1) "one"
2) "two"
3) "three"
127.0.0.1:6379> object encoding one-more-zset
"skiplist"

总结

在Redis中,有序集合的内部实现有压缩列表(ziplist)和跳跃表(skiplist)两种,当集合中的所有元素的成员长度较短并元素个数较少时,使用压缩列表作为内部实现,否则使用跳跃表和哈希表作为内部实现。当条件不满足时,压缩列表可以转换为跳跃表,但跳跃表不能转换为压缩列表。

到此这篇关于Redis中有序集合的内部实现方式的详细介绍的文章就介绍到这了,更多相关Redis有序集合的内部实现内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Redis 相关文章推荐
redis 限制内存使用大小的实现
May 08 Redis
基于Redis过期事件实现订单超时取消
May 08 Redis
浅谈Redis的几个过期策略
May 27 Redis
Redis基于Bitmap实现用户签到功能
Jun 20 Redis
Redis Cluster 集群搭建你会吗
Aug 04 Redis
Redis集群新增、删除节点以及动态增加内存的方法
Sep 04 Redis
Redis+Lua脚本实现计数器接口防刷功能(升级版)
Feb 12 Redis
Redis实现一个账号只能登录一个设备
Apr 19 Redis
Redis特殊数据类型bitmap位图
Jun 01 Redis
Redis基本数据类型String常用操作命令
Jun 01 Redis
Redis sentinel哨兵集群的实现步骤
Jul 15 Redis
Redis配置外网可访问(redis远程连接不上)的方法
Dec 24 Redis
面试分析分布式架构Redis热点key大Value解决方案
分布式架构Redis中有哪些数据结构及底层实现原理
Redis之RedisTemplate配置方式(序列和反序列化)
Mar 13 #Redis
浅谈Redis跟MySQL的双写问题解决方案
解决linux下redis数据库overcommit_memory问题
Feb 24 #Redis
解决Redis启动警告问题
分布式Redis Cluster集群搭建与Redis基本用法
You might like
解析php中heredoc的使用方法
2013/06/17 PHP
浅谈PHP调用Webservice思路及源码分享
2014/06/04 PHP
php将字符串全部转换成大写或者小写的方法
2015/03/17 PHP
效率高的Javscript字符串替换函数的benchmark
2008/08/02 Javascript
自制基于jQuery的智能提示插件一枚
2011/02/18 Javascript
自己动手实现jQuery Callbacks完整功能代码详解
2013/11/25 Javascript
js实现点击左右按钮轮播图片效果实例
2015/01/29 Javascript
JS数组array元素的添加和删除方法代码实例
2015/06/01 Javascript
Jquery中map函数的用法
2016/06/03 Javascript
vue-router路由简单案例介绍
2017/02/21 Javascript
JavaScript引用类型RegExp基本用法详解
2018/08/09 Javascript
JavaScript中的this/call/apply/bind的使用及区别
2020/03/06 Javascript
[01:31](回顾)杀出重围,决战TI之巅
2014/07/01 DOTA
[51:07]VGJ.S vs Pain 2018国际邀请赛小组赛BO2 第一场 8.17
2018/08/20 DOTA
Python中的ctime()方法使用教程
2015/05/22 Python
使用PyCharm配合部署Python的Django框架的配置纪实
2015/11/19 Python
详解python编译器和解释器的区别
2019/06/24 Python
python自带tkinter库实现棋盘覆盖图形界面
2019/07/17 Python
Python基于pyecharts实现关联图绘制
2020/03/27 Python
windows10 pycharm下安装pyltp库和加载模型实现语义角色标注的示例代码
2020/05/07 Python
TripAdvisor越南:全球领先的旅游网站
2017/09/21 全球购物
伊芙丽官方旗舰店:中国淑女一线品牌
2017/12/01 全球购物
美国在线自行车商店:Jenson USA
2018/05/22 全球购物
戴尔马来西亚官网:Dell Malaysia
2020/05/02 全球购物
奥林匹亚体育:Olympia Sports
2020/12/30 全球购物
英国婴儿产品专家:Samuel Johnston
2020/04/20 全球购物
为什么在使用动态 SQL 语句时必须为低层数据库对象授予权限
2012/12/13 面试题
说一下Linux下有关用户和组管理的命令
2016/01/04 面试题
调解员先进事迹材料
2014/02/07 职场文书
教师职称自我鉴定
2014/02/12 职场文书
物流毕业生个人的自我评价
2014/02/13 职场文书
刚毕业大学生自荐信范文
2014/02/20 职场文书
小小的船教学反思
2014/02/21 职场文书
劳资协议书范本
2014/04/23 职场文书
协议书范本
2014/04/23 职场文书
2015年妇产科工作总结
2015/05/18 职场文书