本篇内容主要讲解“复述整数集为什么不能降级”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“复述整数集为什么不能降级”吧!
<编辑类="目录">目录编辑>- <李>
前言
李> <李>基本结构
李> <李>何时使用intset
李> <李>intset
李> <李>添加元素
李> <李>类型变动
李> <李>升级
李> <李>加入65535
李> <李>旧数据移位
李> <李>降级
李> <李>为什么不实现降级
前言
整数集合相信有的同学没有听说过,因为复述对外提供的只有封装的五大对象!而我们本系列主旨是学习复述,内部结构。内部结构是复述,五大结构重要支撑!
前面我们分别从复述,内部结构分析了复述的列表,散列,Zset三种数据结构了。今天我们再来分析组数据结构内部是如何存储的
基本结构
在src/t_set。c中我们发现这样一段代码
由此我们可知在set中是由两种数据结构构成的: hashtable+intset 。关于redis内部其他的结构我专门在【redis专栏中有介绍】。hashtable不是我们今天的主角,我们今天先分析intset俗称整数集合。
从上图中我们可以看出,我构造了两个set集合分别为【commonset】、【cs】。两个集合前者存储字符串、后者专门存储数字。
我们在通过object encoding key
来查看下两个集合的底层数据结构,发现一个是hashtable 一个是intset 。这也验证了我们上面对set基本结构的描述。
在redis中对外提供五大类型实际上都是redis的一个抽象对象叫做redisobject。在内部映射了我们redis内部的数据结构
针对commonset和cs两个集合在内部数据结构大概可以这么理解
何时使用intset
你可以单纯的认为只要是数字就会使用intset结构来存储,我恐怕要给你当头一棒了。实际上并不是这样
需要同时满足以下两个条件:
intset
图中表示的很清楚了,在intset中的encoding有三种取值分别代表contents保存数据类型。这里有人可能会有疑问了contents的类型不就是int8_t吗?为什么还需要encoding呢?这里通过源码跟踪内部的确跟int8_t没啥关系。而且数据的默认类型就是int16_t 。关于length这里无需太多解释,记住一点表示contents元素的个数并非表示contents数组的长度!
了解intset的同学都知道在encoding三种取值范围中涉及了升级的操作!在讲升级之前我们先来了解下C、C++中int的取值范围是如何定义的
int8_t的取值范围是【-128,127】 。 类似于java中byte占1个字节也就是8位。他的取值范围是
添加元素
sadd juejin -123 sadd juejin 6 sadd juejin 12 sadd juejin 56 sadd juejin 321
juejin这个关键内部就是intset。
上面我们添加了5个元素且这五个元素的长度都在16之内!所以当前的intset的编码=intset_enc_int16. - 123在内容中占前16位。
所以当前五个元素占内容的长度是16 * 5=80;
注意设置在存储int类型数据时,内部是按照从小到大的顺序存储的。
类型变动