redis代码解析-dictionary类型
dict本质上是为了解决算法中的查找问题(Searching),一般查找问题的解法分为两个大类:一个是基于各种平衡树,一个是基于哈希表。
redis中的dict传统的哈希算法类似,它采用某个哈希函数从key计算得到在哈希表中的位置,采用拉链法解决冲突,并在装载因子(load factor)超过预定值时自动扩展内存,引发重哈希(rehashing).在一个dict中有两个hash表,目的是来实现逐步的rehash,同时rehash时仍然可以访问dict.
正常使用的是ht[0],在rehash的时候先设置ht[1]大小为rehash后的需要的大小,然后逐步的将ht[0]中的内容rehash到ht[1]中,rehashidx记录着当前rehash到的index,在全部rehash完成之后,将ht[1]给ht[0],再reset ht[1].
当前dict是否处于rehash过程中可以通过rehashidx的值来判断,rehash时记录的是已经进行到的index,非rehash时为-1.
逐步的rehash是将rehash操作分散到对于dict的各个增删改查的操作中去。这种方法能做到每次只对一小部分key进行重哈希,而每次重哈希之间不影响dict的操作。dict这样设计避免重哈希期间单个请求的响应时间的剧烈增加
typedef struct dict {
dictType *type;
void *privdata;
dictht ht[2];
long rehashidx; /* rehashing not in progress if rehashidx == -1 */
unsigned long iterators; /* number of iterators currently running */
} dict;
一个hash table即dictht中的table是一个dictEntry数组,dict每次rehash时,table扩容或者缩小的时候都是2的n次方大小.
同时dictht还记录了当前table的大小,以及存在的dictEntry的数量.判断是否需要rehash就是通过used/size==1为需要rehash,used/size==5需要强制rehash
dictht中sizemask的值为size-1,因为size总是2的n次方,所以sizemask是n位的1,用来一个key的hash&sizemask定位出这个key应该在table中的位置.
同时,解决hash冲突的方法是链式
typedef struct dictEntry {
void *key;
union {
void *val;
uint64_t u64;
int64_t s64;
double d;
} v;
struct dictEntry *next;
} dictEntry; /* This is our hash table structure. Every dictionary has two of this as we
* implement incremental rehashing, for the old to the new table. */
typedef struct dictht {
dictEntry **table;
unsigned long size;
unsigned long sizemask;
unsigned long used;
} dictht;
一个dict的图示如下:
图片引用自:http://zhangtielei.com/posts/blog-redis-dict.html
dict的其他操作都非常简单,都是正常的对hash table的操作
dict scan还有点意思,因为redis中dict数据结构的关系,所以没办法使用传统的顺序遍历,因为
1 如果发生了扩容,原来的表大小是8,扩容之后是16,就会把原来的1-8rehash到新的1-16个slot中.如果现在要顺序访问8,则从8-16之前的其实全部在旧的表中1-7中访问过,会有大量的重复访问.
2 如果发生了缩表,原来的16缩小到8,就正好相反会有遗漏.
3 如果正在rehash,t0表中的数据是不全的也依然肯定有问题.
所以,redis中dict scan设计了一种新的遍历方法:对二进制高位进行加1遍历.
如果表的大小是8的话,和大小为2的访问顺序会是如下:
000 -> 0 00-> 0
100 -> 4 10-> 2
010 -> 2 01-> 1
110 -> 6 11-> 3
001 -> 1
101 -> 5
011 -> 3
111 -> 7
1 表扩容,先访问n,然后是访问n+2的n次方,不会重复,不会遗漏.
2 表缩小,通过n&m0(size mask)定位,可能会有重复的情况,不会遗漏.
3 如果正在rehash过程中,访问n的时候,会先在容量小的表中访问(n&m0),然后在大的表中遍历出全部的n&m0对应的位置.
dict scan 详细可参考这篇blog,http://chenzhenianqing.cn/articles/1101.html
redis代码解析-dictionary类型的更多相关文章
- redis代码解析-事务
redis 的事务相关的几个命令分别为 watch multi exec. watch 可以监控一个变量在事务开始执行之前是否有被修改.使用方式为: WATCH key [key ...] 在redi ...
- Redis源码解析:18Hiredis同步API和回复解析API代码解析
Redis的sentinel模式使用了Hiredis代码,Hiredis是redis数据库一个轻量级的C语言客户端库.它实现的向Redis发送命令的API函数redisCommand,使用方法类似于p ...
- GraphSAGE 代码解析(一) - unsupervised_train.py
原创文章-转载请注明出处哦.其他部分内容参见以下链接- GraphSAGE 代码解析(二) - layers.py GraphSAGE 代码解析(三) - aggregators.py GraphSA ...
- VBA常用代码解析
031 删除工作表中的空行 如果需要删除工作表中所有的空行,可以使用下面的代码. Sub DelBlankRow() DimrRow As Long DimLRow As Long Dimi As L ...
- java集合框架之java HashMap代码解析
java集合框架之java HashMap代码解析 文章Java集合框架综述后,具体集合类的代码,首先以既熟悉又陌生的HashMap开始. 源自http://www.codeceo.com/arti ...
- linux内存管理--slab及其代码解析
Linux内核使用了源自于 Solaris 的一种方法,但是这种方法在嵌入式系统中已经使用了很长时间了,它是将内存作为对象按照大小进行分配,被称为slab高速缓存. 内存管理的目标是提供一种方法,为实 ...
- redis(Remote Dictionary Server)
redis的简介和使用 简介 redis(Remote Dictionary Server)是一种Nosql技术,它是一个开源的高级kv存储和数据结构存储系统,它经常被拿来和Memcached相比 ...
- Redis源代码分析(一)--Redis结构解析
从今天起,本人将会展开对Redis源代码的学习,Redis的代码规模比較小,很适合学习,是一份很不错的学习资料,数了一下大概100个文件左右的样子,用的是C语言写的.希望终于能把他啃完吧,C语言好久不 ...
- C# 获取与解析枚举类型的 DescriptionAttribute
原文:C# 获取与解析枚举类型的 DescriptionAttribute System.ComponentModel.DescriptionAttribute 这个 Attribute,经常被用来为 ...
随机推荐
- element-UI中table表格的row-click事件怎么获取一行数据的id
<el-table :data="tableData" style="width: 100%" @row-click="openDetails( ...
- How do you install Google Chrome on Ubuntu?
https://askubuntu.com/questions/510056/how-to-install-google-chrome sudo apt-get install chromium-br ...
- 在android中读写文件
在android中读写文件 android中只有一个盘,正斜杠/代表根目录. 我们常见的SDK的位置为:/mnt/sdcard 两种最常见的数据存储方式: 一.内存 二.本地 1.手机内部存储 2.外 ...
- php如何将网上的图片下载到本地
<?phpheader("Content-Type: application/force-download");header("Content-Dispositio ...
- UVA-10347 Medians 计算几何 中线定理
题面 题意:已知三角形三中线的长度nmp,求面积 题解:如果知道中线定理就比较简单了 三边长为 3*a=sqrt(8*mb*mb+8*mc*mc-4*ma*ma) 3*b=sqrt(8*ma*ma+8 ...
- Django中的session和cookie及分页设置
cookie Cookie的由来 大家都知道HTTP协议是无状态的. 无状态的意思是每次请求都是独立的,它的执行情况和结果与前面的请求和之后的请求都无直接关系,它不会受前面的请求响应情况直接影响,也不 ...
- 2015 多校赛 第一场 1001 (hdu 5288)
Description OO has got a array A of size n ,defined a function f(l,r) represent the number of i (l&l ...
- 9.19[XJOI] NOIP训练37
上午[XJOI] NOIP训练37 T1 同余方程 Problem description 已知一个整数a,素数p,求解 $x^{2}\equiv a(mod p) $ 是否有整数解 Solution ...
- 在Mac OSX上安装ffmpeg && ffmpeg命令行将h264封装为mp4
ffmpeg功能强大,可以通过命令行来对音视频进行处理.为了使用其功能,我在Mac上对其进行了安装. 我的Mac OS X 系统版本:OS X Yosemite, 10.10.14 关于ffmpeg在 ...
- website robots.txt 防爬虫 措施
robots.txt文件用法举例: 1. 允许所有的robot访问 User-agent: * Allow: / 或者 User-agent: * Disallow: 2. 禁止所有搜索引擎访问网站的 ...