设为首页 收藏本站
查看: 1570|回复: 0

[经验分享] Redis实现原理(2)--字典

[复制链接]

尚未签到

发表于 2015-7-20 10:31:58 | 显示全部楼层 |阅读模式
  1、   Dict   
  2.1 数据结构定义dict.h



// 哈希表结构

typedef struct dictht {
dictEntry **table; //哈希表数组指针

unsigned long size;  //哈希表大小

unsigned long sizemask; //掩码,hash时用到

unsigned long used; //已有节点的数量

} dictht;
//  哈希表节点结构

typedef struct dictEntry {
void *key;
union {
void *val;
uint64_t u64;
int64_t s64;
} v;  // 值,可以是指针类型、uint64和int64
struct dictEntry *next;  //指向下一节点形成一个单链表

} dictEntry;
//字典定义

typedef struct dict {
dictType *type;
void *privdata;
dictht ht[2];
int rehashidx; // 重分布标示-1标示正在重分布中
int iterators; // 重分布进度

} dict;
// 字典类型
// 每个dictType保存了一系列用于操作特定字典的函数,不同用途的字典type不同

typedef struct dictType {
// hash函数

unsigned int (*hashFunction)(const void *key);
// key的复制
void *(*keyDup)(void *privdata, const void *key);
// value的复制
void *(*valDup)(void *privdata, const void *obj);
// key的比较
int (*keyCompare)(void *privdata, const void *key1, const void *key2);
// key的销毁
void (*keyDestructor)(void *privdata, void *key);
// value的销毁
void (*valDestructor)(void *privdata, void *obj);
} dictType;
  
2.2 hash

调用type中得hashFunction方法计算key的hash值,redis内部使用的hash算法为Austin Appleby开发的MurmurHash2算法

h = d->type->hashFunction(key)

计算key的索引值,先在ht[0]中查找,如果没有找到并且在rehash的过程中,则继续在ht[1]中找

idx = h & d->ht[table].sizemask

对于哈希冲突的解决,redis采取的拉链法,相同索引值的key会存储在一个单链表中,所以确定了索引值以后还需要在对应的单链表中进行搜索




while(he) {
if (dictCompareKeys(d, key, he->key))
return -1;
he = he->next;
}
  
2.3 rehash

为了保证字典的使用效率,redis对字典结构采取了定期rehash的机制,因为rehash是重CPU的操作,为了避免过程中出现对外无响应的情况,这里做了一种增量rehash的优化

rehash的流程如下:

  1)   新建一个空得hash表,size为第一个大于等于2n的整数



unsigned long i = DICT_HT_INITIAL_SIZE;
if (size >= LONG_MAX) return LONG_MAX;
while(1) {
if (i >= size)
return i;
i *= 2;
}
  
  2)   将ht[0]中的key重新计算hash和index,索引到ht[1]中,并将ht[0]中相应的索引值置为空
  3)   待ht[0]中的数据全部rehash到ht[1]中之后将ht[1]设置为ht[0],并创建一个新的ht[1]
  增量rehash是对步骤2进行优化,每次只rehash一个index的key,并且在rehash过程中对读写操作做限制:
  1)      读:先查ht[0],如果没有再在ht[1]上查找
  2)      写:rehash过程中,新的key只向ht[1]中写,并且会将索引所对应的所有key重新hash到ht[1]中。
  最终会在某个时间点ht[0]中所有的key重新hash到ht[1]中。
  
  http://www.yancey.info/?p=180

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-88619-1-1.html 上篇帖子: Redis常用命令 下篇帖子: Redis实现分布式锁
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表