Redis(六) 底层数据结构

一、简单动态字符串SDS

  • 结构体成员为两个int类型的整数:len和free,记录字符数组总长度和空闲长度;和一个字符数组
  • 字符数组结尾也像C语言原生字符串一样是’\0’,这样设计是为了复用一些C语言的字符串处理函数。但是因为有len的存在,SDS依然是二进制安全的,即可以存储’\0’,这一点与C原生字符串不同
  • SDS较之C原生字符串的优势:
    • 可以在常数级时间复杂度获取字符串长度
    • 不存在缓冲区溢出的风险
    • 修改字符串时的内存操作次数更少,具体表现在:扩容时,如果修改后字符串长度小于1MB,会直接扩容至两倍长度,否则会分配1MB的预留空间;字符串缩短时也可以直接修改free的值,先不回收对应的内存,而是进行惰性空间删除
    • 二进制安全,前文已述

二、链表

  • 除了链表结构体还实现了一个链表结构体,之中存储了一个指向链表头的指针、一个指向链表尾的指针、一个记录链表长度的变量
  • 为了实现链表存储内容的多态,链表节点采用void*来记录链表节点内容,并且实现了三个方法dup、free、match用于操作节点内容

三、字典

  • Redis的字典底层采用哈希表实现
  • 哈希表的键值对都存储在哈希表节点中,哈希表节点中还存储了指向下个哈希表节点的指针,构成一张链表
  • 哈希表采用MurmurHash2算法作为哈希算法,链地址法作为解决哈希冲突的方法
  • 哈希表使用负载因子评估此时的键值对数量是否过多,是否需要扩容和重哈希
  • 重哈希采用渐进式重哈希的方法,每次对哈希表进行增删改查时,还会将一步分重哈希工作完成

四、跳表

  • 与链表一样,除了跳表节点结构体之外,还有一个跳表结构体用于持有跳表,其中存储了指向跳表头、尾的结构体、目前跳表内层级最高的节点的层级数、跳表长度
  • 跳表节点结构体中存储了层(level),每层都存储了前进指针和跨度(指向的下个节点与当前节点之间的距离)、一个后向指针(可以在从表尾到表头遍历时使用)、当前节点的分值、节点存储的内容
  • 每次新生成一个跳表节点时,会根据幂次定律(power law,越大的数生成几率越小)随机生成一个层数,然后将对应层的上一个节点的前进指针与此节点相连
  • 节点的层中存储的跨度,并不用于遍历跳表,而是用于计算跳表节点的排位(rank),查找某个节点时,将所有跨度相加即可得到节点在跳表中的排位
  • 对于同分值的对象,按照对象的字典序在跳表中从小到大存储
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值