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 ...
随机推荐
- 苹果账号需要的邓白氏D-U-N-S编码更新信息最新方法,官方已不受理邮件
公司从上海搬迁到深圳,公司名称相应变更,但之前注册的苹果开发者账号上的名字还是就的,尝试在后台提交更新申请,官方给了邮件,要求邮件提交证明材料,证明材料提交后,苹果又反馈和邓白氏的资料不匹配,要求先修 ...
- Rust(一)介绍 安装
目录 Rust安装 Rust介绍: Windows 安装步骤: Helle world 创建项目文件夹: 写并执行程序: Rust安装 安装过程简单快捷,直接参照官网即可,Rust安装 Rust介绍: ...
- thinkphp 数据库连接报错 SQLSTATE[HY000] [2002] No such file or directory
https://blog.csdn.net/tornge/article/details/51388233 找到mysql sokcet的路径 vim /etc/mysql/mysql.conf.d/ ...
- css 响应式(媒介查询)
1.CSS 来实现响应式 CSS实现响应式网站的布局要用到的就是CSS中的媒体查询接下来来简单介绍一下: @media 类型 and (条件1) and (条件二){css样式} <link r ...
- JVM加载class文件原理
装载的概念 所谓装载就是寻找一个类或是一个接口的二进制形式并用该二进制形式来构造代表这个类或是这个接口的class对象的过程. Java中类装载器装载类到虚拟机 在Java中,类装载器把一个类装入Ja ...
- Fabric的使用总结
环境说明 建议python版本:2.7 fabric版本:最新版(当前为1.10.2) fabric安装 通过pip.py的方式安装(详细可以在fabric官网了解) fabric执行py文件的方法, ...
- 前端开发本地存储之cookie
1.cookie cookie是纯文本,没有可执行代码,是指某些网站为了辨别用户身份.进行 session 跟踪而储存在用户本地终端(浏览器)上的数据(通常经过加密).当用户访问了某个网站的时候,我们 ...
- Delphi实现获取磁盘空间大小的方法
unit Unit1; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, ...
- HTML与CSS中的文本个人分享
文本 标题元素 注意: 在一个HTML页面中最好只使用一个<h1>标题 因为浏览器只会抓取一个多了没用 示例代码: <body> <!-- 标题元素 - <h1&g ...
- android7.0后对于detected problems with app native libraries提示框显示
log信息: 03-27 09:08:25.887 397 400 W linker : /data/app/com.guagua.qiqi-1/lib/arm/libMedia.so ha ...