面试官:Redis中集合数据类型的内部实现方式是什么?

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容Redis),内存型 2GB
简介: 虽然已经是阳春三月,但骑着共享单车骑了这么远,还有有点冷的。我搓了搓的被冻的麻木的手,对着前台的小姐姐说:“您好,我是来面试的。”小姐姐问:“您好,您叫什么名字?”我回答:“我叫万猫学社。”小姐姐笑出了声,说到:“这名字好怪,谁给你起的啊。”我面无表情地回答:“俺爹。”小姐姐收起了笑容,说到:“跟我来吧。”我被带到了面试间等候,片刻后一个着干净满脸清秀的青年走了进来,一股男士香水的淡香扑面而来。

虽然已经是阳春三月,但骑着共享单车骑了这么远,还有有点冷的。我搓了搓的被冻的麻木的手,对着前台的小姐姐说:“您好,我是来面试的。”小姐姐问:“您好,您叫什么名字?”我回答:“我叫万猫学社。”小姐姐笑出了声,说到:“这名字好怪,谁给你起的啊。”我面无表情地回答:“俺爹。”小姐姐收起了笑容,说到:“跟我来吧。”我被带到了面试间等候,片刻后一个着干净满脸清秀的青年走了进来,一股男士香水的淡香扑面而来。

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

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

面试官:集合数据类型的内部实现方式是什么?

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

面试官:回去等消息吧。

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

类型和编码

首先,整明白什么是类型?什么是编码?在Redis中使用对象来表示内存中的键和值。每个对象由一个叫做redisObject结构体表示,其中有三个属性:类型(type)、编码(encoding)、指向具体数据的指针(ptr)。

我们通常说的字符串、哈希、列表、集合、有序集合都是redisObject中的类型,实际上针对每一个数据结构在Redis内部都有自己底层的多种内部编码实现,这样是为了在合适的场景选择合适的内部编码,以达到内存空间和处理效率的平衡,这可能就是中庸之道吧。

在面试中,经常被问到的内部实现方式、内部构造、内部原理,一般指的就是redisObject中的编码

集合的编码

集合的编码有两种,分别是:整数集合(intset)和哈希表(hashtable)。

当集合中的所有元素都是整数,并且元素的个数小于set-max-intset-entries(默认为512个)时,使用整数集合作为集合的编码,集合的所有元素都保存在整数集合里面。比如:

127.0.0.1:6379> sadd one-more-set 1 2 3 4 5
(integer) 5
127.0.0.1:6379> smembers one-more-set
1) "1"
2) "2"
3) "3"
4) "4"
5) "5"
127.0.0.1:6379> object encoding one-more-set
"intset"

当集合中的所有元素不都是整数,或者元素的个数大于等于set-max-intset-entries(默认为512个)时,使用哈希表作为集合的编码,哈希表的每一个键都是字符串对象,每一个字符串包含一个集合的元素,哈希表的值全部为NULL

比如,集合中的所有元素不是整数:

127.0.0.1:6379> sadd one-more-set one more
(integer) 2
127.0.0.1:6379> smembers one-more-set
1) "more"
2) "one"
127.0.0.1:6379> object encoding one-more-set
"hashtable"

当然,了解以上细节还没能完全“征服”面试官,我们需要更深入一些:)

集合的编码转换

当一个集合是以整数集合为编码时,再向这个集合添加非整数的元素,或向这个集合添加整数的元素使元素个数过多时,就会执行集合的编码转换。

把原来保存在整数集合中的所有元素转移到哈希表中,并且把集合的编码用整数集合修改为哈希表。不过,把非整数的元素从集合中移除,或者减少整数元素的个数,以哈希表为编码的集合也不会转化为整数集合。

举个例子,我们先创建一个以整数集合为编码的集合:

127.0.0.1:6379> sadd one-more-set 1 2 3 4 5
(integer) 5
127.0.0.1:6379> smembers one-more-set
1) "1"
2) "2"
3) "3"
4) "4"
5) "5"
127.0.0.1:6379> object encoding one-more-set
"intset"

然后,再向它添加两个字符串元素,它就是转换为以哈希表为编码:

127.0.0.1:6379> sadd one-more-set one more
(integer) 2
127.0.0.16379> smembers one-more-set
1) "one"
2) "5"
3) "1"
4) "2"
5) "more"
6) "4"
7) "3"
127.0.0.1:6379> object encoding one-more-set
"hashtable"

然后,再把那两个字符串元素从集合中移除,集合的编码依然是哈希表:

127.0.0.1:6379> srem one-more-set one more
(integer) 2
127.0.0.1:6379> smembers one-more-set
1) "5"
2) "1"
3) "2"
4) "4"
5) "3"
127.0.0.1:6379> object encoding one-more-set
"hashtable"

总结

在Redis中,集合的内部实现有整数集合(intset)和哈希表(hashtable)两种,当集合中的所有元素都是整数并元素个数较少时,使用整数集合作为内部实现,否则使用哈希表作为内部实现。当条件不满足时,整数集合可以转换为哈希表,但哈希表不能转换为整数集合。


竟然已经看到这里了,你我定是有缘人,留下你的 点赞关注,他日必成大器。
相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
9天前
|
存储 安全 算法
Java面试题之Java集合面试题 50道(带答案)
这篇文章提供了50道Java集合框架的面试题及其答案,涵盖了集合的基础知识、底层数据结构、不同集合类的特点和用法,以及一些高级主题如并发集合的使用。
26 1
Java面试题之Java集合面试题 50道(带答案)
|
18天前
|
存储 NoSQL Java
可能是最漂亮的Redis面试基础详解
我是南哥,相信对你通关面试、拿下Offer有所帮助。敲黑板:本文总结了Redis基础最常见的面试题!包含了Redis五大基本数据类型、Redis内存回收策略、Redis持久化等。相信大部分Redis初学者都会忽略掉一个重要的知识点,Redis其实是单线程模型。我们按直觉来看应该是多线程比单线程更快、处理能力更强才对,比如单线程一次只可以做一件事情,而多线程却可以同时做十件事情。但Redis却可以做到每秒万级别的处理能力,主要是基于以下原因:(1)Redis是基于内存操作的,Redis所有的数据库状态都保存在
可能是最漂亮的Redis面试基础详解
|
2天前
|
存储 消息中间件 NoSQL
Redis 数据类型
10月更文挑战第15天
8 1
|
6天前
|
NoSQL Java API
美团面试:Redis锁如何续期?Redis锁超时,任务没完怎么办?
在40岁老架构师尼恩的读者交流群中,近期有小伙伴在面试一线互联网企业时遇到了关于Redis分布式锁过期及自动续期的问题。尼恩对此进行了系统化的梳理,介绍了两种核心解决方案:一是通过增加版本号实现乐观锁,二是利用watch dog自动续期机制。后者通过后台线程定期检查锁的状态并在必要时延长锁的过期时间,确保锁不会因超时而意外释放。尼恩还分享了详细的代码实现和原理分析,帮助读者深入理解并掌握这些技术点,以便在面试中自信应对相关问题。更多技术细节和面试准备资料可在尼恩的技术文章和《尼恩Java面试宝典》中获取。
美团面试:Redis锁如何续期?Redis锁超时,任务没完怎么办?
|
12天前
|
NoSQL 算法 Redis
Redis面试篇
Redis面试篇
31 5
|
14天前
|
存储 分布式计算 NoSQL
大数据-40 Redis 类型集合 string list set sorted hash 指令列表 执行结果 附截图
大数据-40 Redis 类型集合 string list set sorted hash 指令列表 执行结果 附截图
21 3
|
13天前
|
缓存 NoSQL Java
Java中redis面试题
Java中redis面试题
25 1
|
14天前
|
消息中间件 分布式计算 NoSQL
大数据-41 Redis 类型集合(2) bitmap位操作 geohash空间计算 stream持久化消息队列 Z阶曲线 Base32编码
大数据-41 Redis 类型集合(2) bitmap位操作 geohash空间计算 stream持久化消息队列 Z阶曲线 Base32编码
20 2
|
18天前
|
NoSQL Redis
redis 的 key 过期策略是怎么实现的(经典面试题)超级通俗易懂的解释!
本文解释了Redis实现key过期策略的方式,包括定期删除和惰性删除两种机制,并提到了Redis的内存淘汰策略作为补充,以确保过期的key能够被及时删除。
37 1
|
2天前
|
存储 缓存 NoSQL
面试官:Redis如何实现延迟任务?
面试官:Redis如何实现延迟任务?
11 0