Redis设计与实现 (三): 字典
哈希表
结构定义dict.h/dictht
- /*
- * 哈希表
- *
- * 每个字典都使用两个哈希表,从而实现渐进式 rehash 。
- */
- typedef struct dictht {
- // 哈希表数组
- dictEntry **table;
- // 哈希表大小
- unsigned long size;
- // 哈希表大小掩码,用于计算索引值
- // 总是等于 size - 1
- unsigned long sizemask;
- // 该哈希表已有节点的数量
- unsigned long used;
- } dictht;
table是一个数组, 每个元素是一个指向dict.h/dictEntry 结构的指针.
哈希表节点
- /*哈希表节点*/
- typedef struct dictEntry {
- // 键
- void *key;
- // 值
- union {
- void *val;
- uint64_t u64;
- int64_t s64;
- } v;
- // 指向下个哈希表节点,形成链表
- struct dictEntry *next;
- } dictEntry;
next属性指向下一个节点, 形成链表, 解决哈希冲突.
字典
- /*
- * 字典
- */
- typedef struct dict {
- // 类型特定函数
- dictType *type;
- // 私有数据
- void *privdata;
- // 哈希表
- dictht ht[];
- // rehash 索引
- // 当 rehash 不在进行时,值为 -1
- int rehashidx; /* rehashing not in progress if rehashidx == -1 */
- // 目前正在运行的安全迭代器的数量
- int iterators; /* number of iterators currently running */
- } dict;
type 和 privdata属性都是针对不同类型的键值对, 为创建多态字典设置.
- /*
- * 字典类型特定函数
- */
- typedef struct dictType {
- // 计算哈希值的函数
- unsigned int (*hashFunction)(const void *key);
- // 复制键的函数
- void *(*keyDup)(void *privdata, const void *key);
- // 复制值的函数
- void *(*valDup)(void *privdata, const void *obj);
- // 对比键的函数
- int (*keyCompare)(void *privdata, const void *key1, const void *key2);
- // 销毁键的函数
- void (*keyDestructor)(void *privdata, void *key);
- // 销毁值的函数
- void (*valDestructor)(void *privdata, void *obj);
- } dictType;
ht数组包含两个哈希表, 一般情况下操作ht[0], ht[1] 只有在ht[0]哈希表进行rehash时使用. rehashidx, 记录了rehash的进度, 没有则为 -1 ;
哈希算法
Redis 使用MurmurHash2算法计算哈希值
解决键冲突
链地址法, 采用头插法, 时间复杂度为O(1).
rehash
1. 为 ht[1] 分配空间 : 如果是扩容, 分配大小为 第一个大于等于 ht[0] .used * 2 的 2的n次幂; 如果是收缩, 分配空间大小为 第一个大于等于 ht[0] .used 的 2的n次幂.
2. 将ht[0] 上的键值对 通过重新计算键的哈希值和索引重新分配到ht[1] 上.
3. 这时ht[0] 将变为空表, 释放ht[0], 将ht[1] 设置为ht[0], 并在ht[1]创建一个空表, 为下次rehash做准备.
渐进式rehash
在字典维持一个索引计数器 rehashidx, 设置为0, 表示正式工作.
在对字典执行添加, 删除, 查找或修改时, 将 rehashidx 索引上的所有键值对 rehash 到 hd[1], 完成后 rehashidx++;
当ht[0] 上的所有键值对被 rehash到 ht[ 1 ], 设置 rehashidx = - 1, 表示操作已经完成了.
在此期间操作数据, 会使用ht[0] 和 ht[1]两个hash表, 例如要找某个键值, 会先在ht[0] 找, 没有就去ht[ 1 ] 找. 新增操作都保存到ht[ 1 ] 中. 保证了ht[0] 只减不增, 最终为空.
Redis设计与实现 (三): 字典的更多相关文章
- [Redis]Redis的设计与实现-链表/字典/跳跃表
redis的设计与实现:1.假如有一个用户关系模块,要实现一个共同关注功能,计算出两个用户关注了哪些相同的用户,本质上是计算两个用户关注集合的交集,如果使用关系数据库,需要对两个数据表执行join操作 ...
- Redis学习笔记(三) 字典
Redis的字典使用哈希表作为底层实现,一个哈希表中可以有多个哈希表节点,而每个哈希节点就保存在字典中的一个键值对. redis字典所用的哈希表由disht结构定义. typedef struct d ...
- Redis 设计与实现 4:字典
Redis 中,字典是基础结构.Redis 数据库数据.过期时间.哈希类型都是把字典作为底层结构. 字典的结构 哈希表 哈希表的实现代码在:dict.h/dictht ,Redis 的字典用哈希表的方 ...
- Redis底层探秘(三):字典
字典,又称为符号表(symbol table).关联数组(associative array)或映射(map),是一种用于保存键值对的抽象数据结构. 字典经常作为一种数据结构内置在很多高级编程语言里面 ...
- Redis设计与实现(一~五整合版)【搬运】
Redis设计与实现(一~五整合版) by @飘过的小牛 一 前言 项目中用到了redis,但用到的都是最最基本的功能,比如简单的slave机制,数据结构只使用了字符串.但是一直听说redis是一个很 ...
- 《Redis设计与实现》读书笔记
<Redis设计与实现>读书笔记 很喜欢这本书的创作过程,以开源的方式,托管到Git上进行创作: 作者通读了Redis源码,并分享了详细的带注释的源码,让学习Redis的朋友轻松不少: 阅 ...
- 《Redis设计与实现》
<Redis设计与实现> 基本信息 作者: 黄健宏 丛书名: 数据库技术丛书 出版社:机械工业出版社 ISBN:9787111464747 上架时间:2014-6-3 出版日期:2014 ...
- 探索Redis设计与实现9:数据库redisDb与键过期删除策略
本文转自互联网 本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutorial ...
- 探索Redis设计与实现6:Redis内部数据结构详解——skiplist
本文转自互联网 本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutorial ...
随机推荐
- JAVA发送HttpClient
http://bijian1013.iteye.com/blog/2310211 在发送HTTP请求的时候会使用到POST和GET两种方式,如果是传送普通的表单数据,我们直接将参数到一个Key-val ...
- shell检查网络出现异常、僵尸进程、内存过低后,自动重启
#!/bin/bash while : do neterror=$(/bin/netstat -a | grep -cw "CLOSE_WAIT") echo "get ...
- jQuery单选框跟复选框美化
在线演示 本地下载
- HTML5相册浏览插件
在线演示 本地下载
- MarkDown初学者使用指南
换MarkDown编辑器了,突然发现自己不会,尴尬!所以顺便总结下Markdown的常用语法 标题 一级标题(格式:#+XXXXX) 二级标题(格式:##+XXXXXX) 三级标题(格式:###+XX ...
- jquery知识location.search
location.search在客户端获取Url参数的方法 location.search是从当前URL的?号开始的字符串如:http://www.baidu.com/s?wd=baidu&c ...
- AtCoder Regular Contest 102
AtCoder Regular Contest 102 C - Triangular Relationship 题意: 给出n,k求有多少个不大于n的三元组,使其中两两数字的和都是k的倍数,数字可以重 ...
- mysql 一些属性
1)定义id,设置int,涉及的属性有: BINARY二进制 UNSIGNED无符号数 UNSIGNED ZEROFILL 在列字段中使用UNSIGNED ZEROFILL属性,如: 插入int(4) ...
- JNI简单步骤01
1.环境变量 1.1.相应的环境变量中,加入如下内容:(Windows) (1).ClASSPATH中输入 : ".;C:\Program Files\Java\jdk1.7.0_07\jr ...
- C-RAN
无线接入网(RAN)是移动运营商赖以生存的重要资产.传统的无线接入网具有以下特点: 1. 每一个基站连接若干个固定数量的扇区天线,并覆盖小片区域,每个基站只能处理本小区收发信号: 2. 系统的容量是干 ...