浅谈Redis底层数据结构(sdshdr-redisObject)

Posted 默辨

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了浅谈Redis底层数据结构(sdshdr-redisObject)相关的知识,希望对你有一定的参考价值。

最近看了点Redis底层的源码分析,特作此记录

前提共识:

  1. Redis是一个默认为16个数据库的key-value内存数据库
  2. Redis底层是由C语言实现

文章目录

下列代码为官网下载的Redis6.2.6版本

C语言源码流程

1、server.c

以该文件中的redisDb结构体为起点

通过注释,我们不难发现*dict指向的,就是我们的单个数据库




2、dict.h

由dict结构体变量开始,代码依次向上调用

该过程可以梳理为:在Redis的一个数据库中,存在两个map结构,这个map的key变量为*key,这个map的value变量为v,并且这个map的节点类似于链表的结构,其内部含有一个同类型并且名字为*next的节点。不知此时你是否意识到,该结构和JDK1.7中HashMap的结构相同,只是在Redis中,这种结构叫做HashTable


补充:

1、ht[2]:表示有两个hashTable表,存放数据时只会使用到一个hashTable表结构,但是该结构会因为数据量过大而出现扩容的情况。与之对应的就是第二个hashTable结构就是用来存放扩容后的新数据集。该扩容过程,采用渐进式hash的过程,即不会在扩容后立刻就完成数据的转移,而是再接下来每次get到数据的时候再进行数据的转移,如果没有get请求,那么redis后台也会慢慢的将数据更新到新的hashTable结构上。最终数据全部完成转移后,老的hashTable结构被释放,新的hashTable被标记为老的结构。待到下次扩容,以此反复。

2、redis数据结构:类比JDK1.7中的HashMap数据结构,数组+链表的数据结构。预分配一个数组用于存放数据,出现hash冲突,向hash桶的位置以头插法的形式添加数据。




3、sds.h

sds可以可以理解为map中每一个entry的key

sds内部含有存放数据的buf数组、一个字节的flags,在sdshdr5的时候用来保存类型和长度,其他几个sdshdrx仅用来保存类型。该sds数据结构在redis3.2以前直接是一个大的sdshdr节点,内含buf、len、free等变量,后续优化数据才出现了下面的按照数据长度进行细分的sdshdr节点。


sds内部buf的扩容机制:新buf长度 = (原buf长度 + 添加buf长度)*2。如果buf长度大于1M后,每次扩容也只会增大1M




4、redisObject

在server.h文件中,含有一个redisObject的结构体,它就是map中entry节点里的value。该结构体是redis中一切value的原型。

  • type:string、list、hash、set、zset。校验客户端操作命令的正确性,一个string类型,不能用lpush命令进行操作
  • encoding:raw、embstr、int、ziplist…。可以在客户端使用object encoding key来查看,作用为查看key对应的value在redis底层使用的是什么数据类型来存储
  • refcount:redis使用引用计数法处理垃圾回收
  • *ptr:真正的指向redis的value在内存中的地址值




5、大体流程

以上是关于浅谈Redis底层数据结构(sdshdr-redisObject)的主要内容,如果未能解决你的问题,请参考以下文章

浅谈Redis

浅谈Java集合(底层源码解析)

浅谈redis

浅谈Java集合丨底层源码解析

浅谈redis和memcached的区别

浅谈索引底层