首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

redis—底层数据结构详解

一、redisObject

在redis中基本的结构对象我们称之为RedisObject,其源码如下:

其中:

type:表示值的数据类型。

encoding:值的编码方式,就是其底层的数据结构实现。

lru:记录了对象最后一次被访问的时间,用于淘汰过期的键值对。

refcount:记录了对象的引用计数。

*ptr:指向数据的指针。

二、String的动态字符串

在redis底层中对,string的表示主要有三种结构,分别是int编码格式;embstr编码格式;raw编码格式。

当长度小于20,并且是数值类型时,其底层就是用long来进行数据存储;这样做的好处就是可以减少空间占用,使用long的话最多也就占8个字节,使用char类型的话,会占用更多的内存空间。

当存储是字符串的数据时,并且字符串的长度小于等于44字节时,以及长度大于22时,RedisObject和SDS会被分配到同一块内存空间,这样可以避免内存碎片化的问题,这种方式称为embstr编码方式。

当存储是字符串的数据时,并且字符串的长度大于44字节时,那么RedisObject和SDS不会被分配在同一片内存空间,这种方式称为raw编码方式

其中SDS即Simple Dynamic String,其构造如下图所示:

其中:

len:占用4个字节,表示buf的已用长度

alloc:占用4个字节,表示buf实际分配的长度

buf:字节数组,保存实际的数据,为了表示字节数组的结束,redis默认在最后加一个"\0"多占用1个字节。

三、List

List数据结构:其底层的数据结构实现是 双向链表 + 压缩链表(ziplist),通过将每个压缩表用双向链表的方式连接起来,来节省内存空间。

ziplist是一个经过特殊编码的双向链表,它的设计目标就是为了提高存储效率,节省内存空间。ziplist可以用于存储字符串或整数,其中整数是按真正的二进制表示进行编码的,而不是编码成字符串序列。它能以O(1)的时间复杂度在表的两端提供push和pop操作。

其中:

zlbytes:表示列表长度

zltail:表示列表尾的偏移量

zllen:表示列表中entry的数量

zlend:用255来表示结束符

每个entry的结构如下:

prev_len:表示前一个entry的长度;有两种表示方式

1字节——取1字节表示前一个entry的长度小于254个字节

5字节——其它长度时,取5字节

encoding:表示编码方式,占用1字节

len:表示自身长度,占4字节

content:保存的实际数据

四、hash

Hash:其底层结构主要有两种方式来实现:hash表(dict)和ziplist,其默认实现是ziplist。

hash结构如下图所示:

并且在redis是存在两个hash表(hash1、hash2),一开始数据量不大的时候,我们的数据都会存放在hash1表中,当我们的key的数量在不断增加的时候,触发我们的rehash过程,这个时候hash2的结构是hash1的2倍,那么这个rehash的过程其实就是每一次操作过程中进行的,每次一个请求,都会讲一个哈希桶的数据放在hash2中,这样可以将操作分散在每个操作中,不会出现系统突然的卡顿现象。其流程如下:

rehash的过程:

给哈希表2分配更大的空间,例如是原来哈希表1的两倍

将哈希表1中的数据重新映射并拷贝到哈希表2中;

释放掉哈希表1中的空间

当发生如下两个情况时ziplist会转化成dict;并且这个过程是不可逆的。

超过ziplist单个entry的长度限制;默认为64bytes

超过ziplist最大entry个数限制:默认是512

五、Set

Set数据结构:其底层主要有整数数组(INTSET)和哈希表两种实现方式。当我们创建set的时候如果遇上成员是整形字符串时,会直接使用intset编码存储。intset的数据结构:

其中:整数数组的一个有序集合,其内部是采用二分查找来定位元素位置。

encoding表示编码格式:表示intset中每个元素采用以下哪种方式存储,有三种类型INT16(2字节),INT32(4个字节),INT64(8个字节)

length:元素个数,表示intset保存在contents中的元素个数

contents:实际存储的数据

每个编码格式的转化如下图所示:

 六、Sorted Set

zset数据结构:即有序的set,其底层时间是ziplist和skiplist。

skiplist结构如下图所示:

其中:skiplist的头部元素是不存储数据的,其值是存储在后面的节点中,span表示的就是步长

header表示头部元素,tail表示尾部元素

length表示元素个数

level表示层级

当符合以下条件中的任意一个时使用skiplist结构存储:

配置了ziplist的最大元素个数为0,即不使用ziplist

配置了ziplist的最大元素个数,并且zset元素大于它

其中zset底层两种结构可以发生相互转化的过程

ziplist转化成skiplist

当ziplist的元素个数大于配置的最大值时,会强制转化成skiplist编码格式(默认128)

当要插入ziplist的元素长度大于配置的最大值时,会强制转化成skiplist编码格式(默认64)

skiplist转换成ziplist

skiplist中元素长度小于配置的ziplist最大值,并且skiplist中元素的最大长度小于等于配置的ziplist元素最大值

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20201121A0F3ZT00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券