面试官:Redis中集合数据类型的内部实现方式是什么?
虽然已经是阳春三月,但骑着共享单车骑了这么远,还有有点冷的。我搓了搓的被冻的麻木的手,对着前台的小姐姐说:“您好,我是来面试的。”小姐姐问:“您好,您叫什么名字?”我回答:“我叫万猫学社。”小姐姐笑出了声,说到:“这名字好怪,谁给你起的啊。”我面无表情地回答:“俺爹。”小姐姐收起了笑容,说到:“跟我来吧。”我被带到了面试间等候,片刻后一个着干净满脸清秀的青年走了进来,一股男士香水的淡香扑面而来。
面试官: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)两种,当集合中的所有元素都是整数并元素个数较少时,使用整数集合作为内部实现,否则使用哈希表作为内部实现。当条件不满足时,整数集合可以转换为哈希表,但哈希表不能转换为整数集合。
最后,谢谢你这么帅,还给我点赞和关注。
微信公众号:万猫学社
微信扫描二维码
关注后回复「电子书」
获取12本Java必读技术书籍

面试官:Redis中集合数据类型的内部实现方式是什么?的更多相关文章
- 面试官:Redis中哈希数据类型的内部实现方式是什么?
面试官:Redis中基本的数据类型有哪些? 我:Redis的基本数据类型有:字符串(string).哈希(hash).列表(list).集合(set).有序集合(zset). 面试官:哈希数据类型的内 ...
- redis中各种数据类型对应的jedis操作命令
redis中各种数据类型对应的jedis操作命令 一.常用数据类型简介: redis常用五种数据类型:string,hash,list,set,zset(sorted set). 1.String类型 ...
- 关于Redis中的数据类型
一. Redis常用数据类型 Redis最为常用的数据类型主要有以下: String Hash List Set Sorted set 一张图说明问题的本质 图一: 图二: 代码: /* Object ...
- Redis 中的数据类型及基本操作
Redis 内置的数据类型有 5种:字符串String.哈希Hash.列表List.集合Set.有序集合ZSet 字符串类型 String 是 Redis 中最基本的类型,一个 key 对应着一个 v ...
- redis中各种数据类型的常用操作方法汇总
在spring中使用jedisTemplate操作,详见https://www.cnblogs.com/EasonJim/p/7803067.html 一.Redis的五大数据类型 1.String( ...
- redis有序集合数据类型---sortedset
一.概述 redis有序集合和集合一样,也是string类型元素的集合,且不允许重复的成员. 不同的是每个元素都会关联一个double类型的分数. redis正式通过分数来为集合中的重圆进行从小到大的 ...
- 搞定面试官 - MySQL 中你知道如何计算一个索引的长度嘛?
大家好,我是程序员啊粥. 今天给大家分享一个我遇到过的比较少见的面试题,那就是 MySQL 中如何计算一个索引的长度. 说实话,我第一次遇到这个问题的时候想当然的以为索引长度就是我们建表时定义的字段长 ...
- JAVA中集合输出的四种方式
在JAVA中Collection输出有四种方式,分别如下: 一) Iterator输出. 该方式适用于Collection的所有子类. public class Hello { public stat ...
- redis中的数据类型
redis不是一个纯文本kv存储,实际上,它是一个数据结构服务,支持不同类型的value. 包含以下类型: 1.Binary-safe strings. 二进制安全的字符串 2.Lists: coll ...
随机推荐
- 将string字符串中的换行符进行替换
/** * 方法名称:replaceBlank * 方法描述: 将string字符串中的换行符进行替换为"" * */ public static String replaceBl ...
- linux 多个C源文件编译
转载请注明来源:https://www.cnblogs.com/hookjc/ 如果有多个源文件,基本上有两种编译方法: [假设有两个源文件为test.c和testfun.c] 1. 多个文件一起编译 ...
- PHP中英文混合字符串处理
转载请注明来源:https://www.cnblogs.com/hookjc/ function cut_str($string, $sublen, $start = 0, $code = 'utf- ...
- elasticsearch搜索引擎的常用方法
1.term和termsterm和terms等查询,不会对查询对字段进行分词处理,适合于date.num.id等确切数据进行搜索 如果需要查询keywords,则查询等keywords必须是查询字段中 ...
- python篇第10天【For 循环语句】
实例 #!/usr/bin/python # -*- coding: UTF-8 -*- for a in 'Henry': print "This is ", a fru ...
- PHP+mysql真题
PHP+mysql真题 来自<PHP程序员面试笔试宝典>,涵盖了近三年了各大型企业常考的PHP面试题,针对面试题提取出来各种面试知识也涵盖在了本书. [真题215] 按要求写出SQL实现. ...
- Solution -「UR #21」「UOJ #632」挑战最大团
\(\mathcal{Description}\) Link. 对于简单无向图 \(G=(V,E)\),定义它是"优美"的,当且仅当 \[\forall\{a,b,c,d\ ...
- Note -「Mobius 反演」光速入门
目录 Preface 数论函数 积性函数 Dirichlet 卷积 Dirichlet 卷积中的特殊函数 Mobius 函数 & Mobius 反演 Mobius 函数 Mobius 反演 基 ...
- macbook安装scala、hadoop、saprk环境
一.scala安装 1. 安装jdk 有mac专用的jdk安装包,这里下载安装jdk1.8 2. 安装scala 2.1下载scala 2.2解压到指定目录 tar -zxvf /Users/lode ...
- JMM之synchronized关键字
对于通讯,涉及两个关键字volatile和synchronized: Java支持多个线程同时访问一个对象或者对象的成员变量,由于每个线程可以拥有这个变量的拷贝(虽然对象及其成员变量分配的内存实在共享 ...