浅谈Redis底层数据结构(sdshdr-redisObject)
Posted 默辨
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了浅谈Redis底层数据结构(sdshdr-redisObject)相关的知识,希望对你有一定的参考价值。
最近看了点Redis底层的源码分析,特作此记录
前提共识:
- Redis是一个默认为16个数据库的key-value内存数据库
- 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)的主要内容,如果未能解决你的问题,请参考以下文章