讲讲redis底层数据结构吧

redis有五种对象类型,分别是字符串、列表、哈希、集合、有序集合,redis的键值对是两个对象,键一般是字符串,值就这五种中选了。

字符串

字符串的编码可以了解下SDS,全称Simple Dynamic String

和C语言中的字面量String相比,SDS优势主要以下几点

  1. 提供了len属性,O(1)获取长度

  2. 动态扩展,C语言中的String占多少内存是固定的,进行拼接之类操作如果不提前分配好空间的话就会出错。SDS提供了free属性,表示buf数组中未曾使用的字节数量,这个属性主要是基于空间预分配来的,提前分配好大于当前字符串的字节量给buf,避免了缓冲区溢出。同时,如果字符串变小省下的空间也给free记下来留作后用

字符串是唯一可以嵌套在其他四个对象中的对象类型

redis提前缓存了0-9999这10000个字符串,可以共享使用

列表

列表的底层编码有ziplistlinkedList两种,每个节点表示一个元素

ziplist由压缩列表实现,压缩列表是一系列特殊编码的连续内存块构成的s顺序型存贮结构,一般在数据较小或数据量少的情况下使用;如果数据多的话,底层会切换为LinkeList,即双端链表

ziplist的爆炸问题

ziplist的节点中有一个属性存贮前一个节点的长度,这个属性使得压缩列表可以从表尾向表头节点进行遍历,如果我们拥有指向当前节点的地址的指针,就可以利用这个属性向前回溯。

该属性长度可以是1字节或者5字节(根据前一个节点长度是否<254),连锁更新的问题由此而来

一连串的250-253字节大小的节点,所以这些节点的previous_entry_length大小都是1,若是在表头加一个255字节的,那么后边第一个的previous_entry_length就由1变成5,这第一个变化的节点大于254,后边以此继续下去造成连锁更新。

哈希

哈希编码主要有ziplisthashtable两种

ziplist在保存的键和值的长度都较小或者保存的键值对数量较少时使用,否则使用hashtable,hashtable的底层使用字典来实现。

如果使用ziplist,键值紧密相连,类比于使用bitmap存贮数字的出现情况。两个紧密相连的位表示一个数字,一个位表示数字本身,另一个位表示数字的出现情况(1次/大于1次)。在ziplist中也是两块紧密相连的位置,一块是key,一块是value。
在这里插入图片描述

字典中有hash表,其实就跟hashmap差不多。字典的结构中包括两个hash表,h[0]和h[1],每次只是用h[0]就够了,若是需要扩容,就一部分一部分的迁移到h[1],在此过程中,若是客户端线程来删改查数据,先从h[0]找,没有的话去h[1],若是添加数据,直接添加到h[1],保证H[0]数据不增加。最后迁移完成释放h[0],将h[1]设置为h[0],再在h[1]新建一个空白哈希表

字典中使用MurmurHash算法计算哈希值

集合

集合的编码有intset****和hashtable

当集合保存的对象都是整数或集合内的元素数量少的话可以使用intset,否则使用hashtable编码

hashtable的编码的集合对象底层使用字典实现,键是保存的对象,值是null

有序集合

有序集合的编码主要是ziplistskiplist

还是元素小或者元素数量少的时候使用ziplis,数据大的话使用zset

ziplist编码的有序集合实现是压缩列表,两个节点保存一个元素,分别保存元素成员和元素分值,集合元素在压缩列表内按分值大小排序

skiplist编码的有序集合底层使用zset实现,zset包含一个跳跃表和字典。跳跃表中可以保存元素成员和分值,有序性也完全是基于跳表实现的。
跳表的查找的效率平均是O(logN),最坏是O(N)。通过跳表可以实现ZRANK、ZRANGE等命令,那么为什么还需要字典呢?主要是为了O(1)通过元素成员得到分数,如果不使用字典,我们最起码需要先O(logN)找到该元素再查分数。相反,如果不适用跳表只使用字典,字典是无序的,那使用ZRANGE等命令时,需要先排序,复杂度至少是O(NlogN).

跳表和字典中的元素成员和分数共用同一个地址,并没有冗余存贮

redis中的内存回收

主要是使用引用计数,熟悉java gc的话这里应该不陌生,我猜主要是因为引用计数不需要STW

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值