redis底层数据结构

调试redis的命令

cd redis-6.0.0 – 进入redis目录

redis服务器端 启动gdb、redis
1、gdb --args ./src/redis-server redis.conf
2、设置断点 b 文件名:函数名
3、输入 c
等待客户端触发断点

redis的结构

Redis 整体就是 哈希表来保存所有的键值对,无论数据类型是 5 种的任意一种。哈希表,本质就是一个数组,每个元素被叫做哈希桶,不管什么数据类型,每个桶里面的 entry 保存着实际具体值的指针。

在这里插入图片描述

Redis中使用的hash算法是siphash算法,siphash就可以将字符串hash为64位的 二进制数,并且能够很好的处理有特征的key。 Redis中key的特征是有规律,具有强随机分布性,就是保证key的随机分布。

Redis中key存储的类型都会变为string。
value可以存储的类型包括:string、hash、set、zset、list、stream。

rehash

当写入 Redis 的数据越来越多的时候,哈希冲突不可避免,会出现不同的 key 计算出一样的哈希值。

Redis 通过链式哈希解决冲突:也就是同一个 桶里面的元素使用链表保存。但是当链表过长就会导致查找性能变差可能,所以 Redis 为了追求快,使用了两个全局哈希表。用于 rehash 操作,增加现有的哈希桶数量,减少哈希冲突。

redis中的哈希表, 初始值只有长度为4,因此需要适当的进行扩容或者在数据量减少的时候需要进行缩容。具体的扩容的方法就是将存放元素的数组的size翻倍,但是需要注意的是在进行持久化操作的时候,比如rdb、aof操作时,这时候是不能申请内存的,因此需要等到操作结束之后进行扩容。缩容的话是当数据量小于数组长度的10%(也就是负载因子ratio <0.1)的时候进行,因为需要防止,反复缩容扩容的情况。

关于rehash还需要思考一个问题,当有数组中有大量数据的时候,如果还需要对数组进行扩容的话,这个时候如果正常操作rehash会非常耗时,因此使用渐进式rehash,
详细的步骤为:
1. 为 ht[1] 分配空间, 让字典同时持有 ht[0] 和 ht[1] 两个哈希表。
2. 在字典中维持一个索引计数器变量 rehashidx , 并将它的值设置为 0 , 表示 rehash 正式开始。
3. 在 rehash 进行期间, 每次对字典执行添加、删除、查找或者更新操作时, 程序除了执行指定的操作以外, 还会顺带将 ht[0] 哈希表在 rehashidx 索引上的所有键值对 rehash 到 ht[1] , 当 rehash 工作完成之后, 程序将 rehashidx 属性的值增。
如果没有持久化操作的话就定时进行rehash,具体实现是1ms内操作多轮100次。如果有持久化操作的话就是执行一次rehash,一次rehash一个数组中元素下面挂的一个链表。
4. 随着字典操作的不断执行, 最终在某个时间点上, ht[0] 的所有键值对都会被 rehash ht[1] , 这时程序将 rehashidx 属性的值设为 -1 , 表示 rehash 操作已完成。
渐进式 rehash 的好处在于它采取分治的方式, 将 rehash 键值对所需的计算工作均滩到对字典的每个添加、删除、查找和更新操作上,甚至是后台启动定时器,每次时间循环时只工作1毫秒, 从而避免了集中式 rehash 带来的庞大计算量。

跳表

sorted set 类型的排序功能便是通过「跳跃列表」数据结构来实现。
跳跃表(skiplist)是一种有序数据结构,它通过在每个节点中维持多个指向其他节点的指针,从而达到快速访问节点的目的。

跳跃表支持平均 O(logN)、最坏 O(N)复杂度的节点查找,还可以通过顺序性操作来批量处理节点。
跳表在链表的基础上,增加了多层级索引,通过索引位置的几个跳转,实现数据的快速定位,如下图所示:
在这里插入图片描述

当需要查找 40 这个元素需要经历 三次查找。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值