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五大数据结构和使用场景
Apr 12 Redis
Redis IP地址的绑定的实现
May 08 Redis
使用Redis实现秒杀功能的简单方法
May 08 Redis
详解Redis瘦身指南
May 26 Redis
redis 存储对象的方法对比分析
Aug 02 Redis
Redis Cluster 集群搭建你会吗
Aug 04 Redis
Redisson实现Redis分布式锁的几种方式
Aug 07 Redis
Redis 持久化 RDB 与 AOF的执行过程
Nov 07 Redis
Redis中有序集合的内部实现方式的详细介绍
Mar 16 Redis
redis sentinel监控高可用集群实现的配置步骤
Apr 01 Redis
利用Redis实现点赞功能的示例代码
Jun 28 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之PHP语法学习笔记1
2006/12/17 PHP
DW中链接mysql数据库时,建立字符集中文出现乱码的解决方法
2010/03/27 PHP
php通过文件头检测文件类型通用代码类(zip,rar等)
2010/10/19 PHP
CI框架整合smarty步骤详解
2016/05/19 PHP
如何判断php mysqli扩展类是否开启
2016/12/24 PHP
PHP设计模式之单例模式原理与实现方法分析
2018/04/25 PHP
jquery 弹出层实现代码
2009/10/30 Javascript
jQuery插件Zclip实现完美兼容个浏览器点击复制内容到剪贴板
2015/04/30 Javascript
js实现鼠标滑过文字链接色彩变化的效果
2015/05/06 Javascript
jQuery实现的自定义弹出层效果实例详解
2016/09/04 Javascript
基于Nodejs利用socket.io实现多人聊天室
2017/02/22 NodeJs
jQuery实现三级联动效果
2017/03/02 Javascript
Vue实现PopupWindow组件详解
2018/04/28 Javascript
vue实现微信分享功能
2018/11/28 Javascript
js取0-9随机取4个数不重复的数字代码实例
2019/03/27 Javascript
如何基于vue-cli3.0构建功能完善的移动端架子
2019/04/24 Javascript
vue图片加载失败时用默认图片替换的方法
2019/08/29 Javascript
解决vue打包报错Unexpected token: punc的问题
2020/10/24 Javascript
举例讲解Python设计模式编程中的访问者与观察者模式
2016/01/26 Python
读写json中文ASCII乱码问题的解决方法
2016/11/05 Python
Python 数值区间处理_对interval 库的快速入门详解
2018/11/16 Python
opencv python统计及绘制直方图的方法
2019/01/21 Python
Python画图实现同一结点多个柱状图的示例
2019/07/07 Python
django的auth认证,authenticate和装饰器功能详解
2019/07/25 Python
Python爬取腾讯视频评论的思路详解
2019/12/19 Python
git查看、创建、删除、本地、远程分支方法详解
2020/02/18 Python
Django 解决阿里云部署同步数据库报错的问题
2020/05/14 Python
使用keras实现非线性回归(两种加激活函数的方式)
2020/07/05 Python
Pycharm快捷键配置详细整理
2020/10/13 Python
CSS3实现多重边框的方法总结
2016/05/31 HTML / CSS
导出HTML5 Canvas图片并上传服务器功能
2019/08/16 HTML / CSS
C++如何引用一个已经定义过的全局变量
2014/08/25 面试题
会计专业职业规划:规划自我赢取未来
2014/02/12 职场文书
绩效管理实施方案
2014/03/19 职场文书
社区国庆节活动总结
2015/03/23 职场文书
python使用torch随机初始化参数
2022/03/22 Python