首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

redis源码:数据结构实现

redis源码:数据结构实现

list

源码目录adlist.h adlist.c

底层数据结构双向链表

节点源码

typedefstructlistNode{

// 前置节点

structlistNode*prev;

// 后置节点

structlistNode*next;

// 值

void*value;

}listNode;

链表源码

typedefstructlist{

// 头节点

listNode*head;

// 尾节点

listNode*tail;

// 节点值复制函数

void*(*dup)(void*ptr);

// 节点值释放函数

void(*free)(void*ptr);

// 节点值对比函数

int(*match)(void*ptr,void*key);

// 链表所包含的节点数量

unsignedlonglen;

}list;

图解说明

特点

可以很容易获取当前节点的前一个节点和后一个节点

没有环结构,所有的节点以空节点结束

链表自带长度计数器,获取链表节点个数的时间复杂度为O(1)

hash

源码目录dict.h dict.c

底层数据结构哈希表说明:在redis中解决hash冲突的方式为采用链地址法。key和v分别用于保存键值对的键和值

哈希表

typedefstructdictht{

// 哈希表数组,数组的每个元素都指向dictEntry结构指针

//链地址法解决哈希冲突

dictEntry**table;

// 哈希表大小,且一定是2的幂

unsignedlongsize;

// 哈希表大小掩码,用于计算索引值

// 总是等于 size - 1

unsignedlongsizemask;

// 该哈希表已有节点的数量

unsignedlongused;

}dictht;

字典

typedefstructdict{

// 类型特定函数

dictType*type;

// 私有数据

void*privdata;

// 哈希表

dicththt[2];

// rehash 索引

// 当 rehash 不在进行时,值为 -1

intrehashidx;/* rehashing not in progress if rehashidx == -1 */

// 目前正在运行的安全迭代器的数量

intiterators;/* number of iterators currently running */

}dict;

图解说明

里面包含了一个特别重要的东西:rehash,单独拎出来总结

节点源码

typedefstructdictEntry{

void*key;//键

union{

void*val;//值

uint64_tu64;

int64_ts64;

doubled;

}v;

structdictEntry*next;//指向下一个节点,形成链表

}dictEntry;

总结

redis中字典使用哈希表作为底层实现的,每个字典带有两个哈希表,一个日常使用,另外一个作为rehash时使用;

哈希表解决冲突的方式是使用链地址法

哈希表进行扩展或者是收缩的时候,采用的是rehash的方式,这个过程是渐进式的;

zset

跳跃表节点源码

typedefstructzskiplistNode{

// 成员对象

robj*obj;

// 分值

doublescore;

// 后退指针

structzskiplistNode*backward;

// 层

structzskiplistLevel{

// 前进指针

structzskiplistNode*forward;

// 跨度

unsignedintspan;

}level[];

}zskiplistNode;

跳跃表

typedefstructzskiplist{

// 表头节点和表尾节点

structzskiplistNode*header,*tail;

// 表中节点的数量

unsignedlonglength;

// 表中层数最大的节点的层数

intlevel;

}zskiplist;

图解

总结

每个跳跃表节点的层高都是在1到32之间的随机数

在同一跳跃表中,多个节点可以包含相同的分值,但是每个节点的成员对象必须是唯一的;

跳跃表中的节点按照分值的大小进行排序的,当分值相同时,节点按照成员对象的大小进行排序

set

源码目录insert.h insert.c

低层数据结构数组

源码

typedefstructintset{

// 编码方式

uint32_tencoding;

// 集合包含的元素数量

uint32_tlength;

// 保存元素的数组

int8_tcontents[];

}intset;

升级操作

1.根据新元素的类型,扩展整数集合数组的大小,并为新元素分配空间

2.将低层数组现有的所有元素都转换成与新元素相同的类型,并将类型转换后的元素放置到正确的位置,在放置元素的过程中,需要维持低层的数组的有序性质不变;

3.将新元素添加到低层数组中;

总结

集合的低层实现是数组;它是有序、无重复的方式保存;

只支持升级操作,不支持降级操作

升级操作可以有效的节省内存,而且可以根据新增元素的类型扩展相应的数据类型;

想了解学习更多C++后台服务器方面的知识,请关注:微信公众号:====CPP后台服务器开发====

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20200308A069IP00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券