Redis底层数据结构和value值的类型

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Xtick/article/details/81900810

看到好多文章直接写Redis有5种数据结构,这种表达不准确,我根据《Redis设计与实现》中的内容进行了简单的整理。

Redis数据库里面的每个键值对都是有对象组成的,其中:

  • 数据库键总是一个字符串对象
  • 数据库值则可以使字符串对象、列表对象、哈希对象、集合对象、有序集合对象这5种对象中的其中一种

——《Redis设计与实现》


Redis 主要有7种数据结构: SDS(简单动态字符串)、链表、字典、跳跃表、整数集合、压缩列表 、对象
Redis 对象系统包含5种对象:字符串对象、列表对象、哈希对象、集合对象、有序集合对象

底层数据结构:

SDS:

Redis没有直接使用C语言中传统字符串表示,而是实现了SDS(simple dynamic string)作为默认字符串表示。C字符串只会作为字符串字面量由于无需修改的地方,比如日志打印。
SDS的结构如下所示,该图展示的是一个代表“Redis”字符串的SDS。其中len和free的“5”单位是Byte。虽然SDS保留了C中的空字符‘/0’但是它不会被计算到len中。
SDS数据结构
比起C字符串,SDS具有以下优点:

  • 常数复杂度获取字符串长度(由于len字段的存在)
  • 杜绝缓冲区溢出(C在追加字符串时,会默认已经分配了足够的内存,所以如果没有分配足够的内存就会造成溢出;而SDS在执行修改的时候API会先检查SDS空间是否满足需求)
  • 减少修改字符串长度时所需的内存重分配次数(空间预分配:当API对SDS进行修改,不仅会分配必要空间,还会分配额外空间,小于1MB时会分配和len大小相同的free,大于1MB会分配1MB的未使用空间;惰性空间释放:程序不立即使用内存重分配来回收缩短后多出来的字节,而是使用free属性记录)
  • 二进制安全(C字符串使用‘/0’空字符来判断字符串是否结束,所以C字符串无法存储图像、音频等这样的二进制,而SDS使用len来判断字符串是否结束)
  • 兼容部分C字符串函数

链表:

链表
(这里dup、free、match都是函数)
链表特性:双端(每个节点都有前后指针)、无环(表头的prev和表尾next指向NULL)、带表头和表尾指针、带链表长度计数器、多态(链表可以保存各种不同类型的值)

字典:

字典的实现和hashMap很像。
字典

rehash:

可以看到图中的ht[1]的这个哈希表是空的,当ht[0]中保存的键值对过大或过小时,就会为ht[1]分配空间进行rehash,如果是扩展操作,那么ht[1]的大小为第一个大于等于ht[0].used * 22^n,如果是收缩操作,那么ht[1]的大小为第一个大于等于ht[0].used的2^n。rehash之后,ht[0]和ht[1]会互相调换。
字典的rehash是渐进式的,在进行渐进式rehash的过程中,字典会同时使用ht[0]和ht[1]两个哈希表,所以在渐进式rehash期间,字典的增删改查等操作会在两个哈希表上进行,例如查找一个键,会先去ht[0]查找,找不到就去ht[1]查找,新添加的键一律都是存到ht[1]中,ht[0]包含的键值只减不增。

跳跃表:

大部分情况下,跳跃表效率和平衡树媲美,实现又比平衡树简单,所以许多情况下会用跳跃表来代替平衡树。
跳跃表
每创建个跳跃表节点时,程序会根据幂次定律(越大的数出现概率越小)随机生成一个1~32之间的值作为层的高度大小,每个层都有前进指针和跨度。每个节点包含层、后退指针、分值、成员对象。

整数集合:

整数集合

升级:

每当一个新元素添加到整数集合里面,并且新元素类型比整数集合现在所有元素的类型都要长时,整数集合需要先进行升级,然后才能将新元素添加到整数集合里面。升级需要扩展底层数组空间大小,为新元素分配空间,并将所有元素转换成与新元素相同的类型。整数集合不支持降级。

压缩列表:

压缩列表是Redis为了节约内存而开发的,是由一系列特殊编码的连续内存块组成的顺序型数据结构。
压缩列表
压缩列表节点
压缩列表可能存在连锁更新的问题,但是发生的概率不高,所以对性能的影响几率很低。

对象:

Redis没有直接使用上述的这些底层数据结构来实现键值对数据库,而是基于这些数据结构创建了一个对象系统,这个系统包含**字符串对象、列表对象、哈希对象、集合对象、有序集合对象**5种,每种对象都用到了至少一种上述的数据结构。Redis使用了基于引用计数的方式来实现内存回收;同时基于引用计数实现了对象共享机制。
Redis对象系统
type:一共有5种,REDIS_STRING、REDIS_LIST、REDIS_HASH、REDIS_SET、REDIS_ZSET
ptr:ptr指针指向对象的底层实现数据结构
encoding:ptr指向哪种数据结构由encoding属性决定
下图展示的是type和encoding的对应关系,即是在type确定时可以使用那些encoding配合:
type和encoding对应关系

参考链接:

猜你喜欢

转载自blog.csdn.net/Xtick/article/details/81900810