Redis设计与实现 -- 链表与字典
1. 链表
1.1 链表的结构

在 Redis 中,链表的实现是双向链表,除此之外与常规的链表不同的是它还有三个函数指针,dup 函数用于复制链表节点所保存的值,free 函数用于释放链表节点保存的值,match 函数则用于对比链表节点的值和另一个值是否相等。
1.2 总结

2. 字典
2.1 字典的定义
Redis 的字典与 C++ 的 map 类似,key 与 value 进行关联,一个字典可以包含多个键值对。
2.2 哈希表的实现
Redis 的字典底层实现为哈希表,一个哈希表有多个哈希节点,每个哈希节点保存着一个键值对。Redis 的哈希表结构定义如下。

其中 table 为一个 dictEntry 数组,每个元素保存着一个键值对, dictEntry 的结构定义如下。

为了防止哈希后键冲突,dictEntry 设计了一个 next 字段,形成了一个链表,键冲突后的结构如下图所示:

2.3 字典

在 dict 结构体中 ht 字段是一个长度为 2 的数组,每个元素都是一个 dictht 哈希表,默认使用 ht[0],ht[1] 在对 ht[0] 进行 rehash 的时候使用,trehashidx 表示 rehash 的进度,值为 -1 的时候表示目前没有在 rehash。普通状态下的 dict (没有 rehash)如下所示

2.4 哈希算法


2.5 键冲突
当有多个键被分配到哈希数组的同一索引上时,则产生了键冲突,Redis 解决该问题的方法是使用链地址法,即每个节点都有一个 next 指针, 多个哈希表的节点可以使用 next 指针连接起来,由于 dictEntry 节点组成的链表没有指向尾部的指针,如果在尾部插入需要 O(N) 的时间复杂度,考虑到效率问题,总是将新节点插入在链表的头部。

以上图为例,插入一个新的 dictEntry 节点,键值对为 k2, v2,可以看出是插入到头部的。
2.6 rehash
当哈希表的键值对过多或者过少时,会对哈希表的大小进行相应的扩展或者收缩。rehash 的步骤如下:



哈希表的扩展收缩都是自动的,当以下条件满足时自动开始对哈希表进行扩展动作:
- 服务器目前没有执行 BGSAVE 命令或者 BGREWRITEAOF 命令且哈希表的负载因子大于等于 1 。
- 服务器目前正在执行 BGSAVE 命令或者 BGREWRITEAOF 命令且哈希表的负载因子大于等于 5 。
负载因子的计算公式为:ht[0].used / ht[0].size 。如一个大小为 512,包含 256 个键值对的哈希表来说, 其 负载因子为 256 / 512 = 0.5,当负载因子小于 0.1 时,自动执行收缩操作。
2.7 渐进式 rehash
哈希表的扩展和收缩是将所有的键值对 rehash 到 ht[1] 中,而这个 rehash 的过程不是一次性将所有的键值对 rehash 过去,而是分多次渐进式的进行,原因在于当键值对过多,如数百万个时,计算量过于庞大可能导致服务器在一段时间停止服务。这种渐进式的 rehash 步骤如下:





Redis设计与实现 -- 链表与字典的更多相关文章
- Redis 设计与实现 4:字典
Redis 中,字典是基础结构.Redis 数据库数据.过期时间.哈希类型都是把字典作为底层结构. 字典的结构 哈希表 哈希表的实现代码在:dict.h/dictht ,Redis 的字典用哈希表的方 ...
- 2.redis设计与实现--链表
1.链表节点: 2.链表: 3.总结
- Redis 设计与实现 8:五大数据类型之哈希
哈希对象的编码有两种:ziplist.hashtable. 编码一:ziplist ziplist 已经是我们的老朋友了,它一出现,那肯定就是为了节省内存啦.那么哈希对象是怎么用 ziplist 存储 ...
- Redis 设计与实现 9:五大数据类型之集合
集合对象的编码有两种:intset 和 hashtable 编码一:intset intset 的结构 整数集合 intset 是集合底层的实现之一,从名字就可以看出,这是专门为整数提供的集合类型. ...
- [Redis]Redis的设计与实现-链表/字典/跳跃表
redis的设计与实现:1.假如有一个用户关系模块,要实现一个共同关注功能,计算出两个用户关注了哪些相同的用户,本质上是计算两个用户关注集合的交集,如果使用关系数据库,需要对两个数据表执行join操作 ...
- redis 笔记01 简单动态字符串、链表、字典、跳跃表、整数集合、压缩列表
文中内容摘自<redis设计与实现> 简单动态字符串 1. Redis只会使用C字符串作为字面量,在大多数情况下,Redis使用SDS(Simple Dynamic String,简单动态 ...
- Redis数据结构—链表与字典的结构
目录 Redis数据结构-链表与字典的结构 链表 Redis链表节点的结构 Redis链表的表示 Redis链表用在哪 字典 Redis字典结构总览 Redis字典结构分解 Redis字典的使用 Re ...
- Redis数据结构—链表与字典
目录 Redis数据结构-链表与字典 链表 Redis链表节点的结构 Redis链表的表示 Redis链表用在哪 字典 Redis字典结构总览 Redis字典结构分解 哈希算法 解决键冲突 rehas ...
- Redis设计与实现 (二): 链表
Redis实现为双链表结构, 列表键的底层实现之一就是链表, 发布与订阅, 慢查询, 监视器等功能都用到了链表. Redis本身也使用链表维持多个客户端. 节点定义, 位于 adlist.h/lis ...
随机推荐
- LinuxC语言实现ATM取款机实验Socket
链接:https://pan.baidu.com/s/1sZt4qhYc6CDJVpoJHbtw-Q 提取码:53ot 复制这段内容后打开百度网盘手机App,操作更方便哦 本实验用的是Centos7t ...
- Read-Only Tables 只读表
Put a table into read-only mode,which prevents DDL or DML changes during table maintenance Put the ...
- 什么是shader?
一.什么是shader? shader是一段GLSL(openGL着色语言)小程序,运行在GPU(图形处理器),而非CPU使用GLSL语言编写,看上去像c或c++,但却是另外一种不同的语言.使用sha ...
- node.js从入门到放弃《模块》
在计算机程序的开发过程中,随着程序代码越写越多,在一个文件里代码就会越来越长,越来越不容易维护. 为了编写可维护的代码,我们把很多函数分组,分别放到不同的文件里,这样,每个文件包含的代码就相对较少,很 ...
- [python 学习] 使用 xml.etree.ElementTree 模块处理 XML
---恢复内容开始--- 导入数据(读文件和读字符串) 本地文件 country_data.xml <?xml version="1.0"?> <data> ...
- Zabbix通过邮件发送Screen图形报表实现
在使用Zabbix的过程中,我们通常会建立一些需要的Screen图形报表来汇总需要监控的Graph. 而下面的两个脚本,则是通过从Zabbix数据库中获取所有的Screen图形参数,提供Zabbix的 ...
- BZOJ 4804: 欧拉心算 欧拉函数
Description 给出一个数字N Input 第一行为一个正整数T,表示数据组数. 接下来T行为询问,每行包含一个正整数N. T<=5000,N<=10^7 题解: 求 $\sum_ ...
- vue项目适应不同屏幕做的适配器
一般宽度是1920的,但是有的电脑屏幕很窄,导致页面样式错乱,那么可以设置app.vue以及主页面里的样式宽度为1920px,超过了就auto. 如下: (app.vue) (home.vue) 原效 ...
- 提示”The following modules are missing or built with a different engine version”
一台机器使用自行编译版本引擎修改了工程后,另一台机器也使用自行编译版本引擎编辑该工程,有时会出现标题的提示 解决办法: 打开\Engine\Binaries\Win64\UE4Editor.modul ...
- HTTP请求时候总是设置的两个参数ConnectionTimeOut和SocketTimeOut
在HTTP请求时候总是设置两个参数,就是连接超时和Socket超时 public static final String SO_TIMEOUT = "http.socket.timeout& ...