哈希表

结构定义dict.h/dictht

  1. /*
  2. * 哈希表
  3. *
  4. * 每个字典都使用两个哈希表,从而实现渐进式 rehash 。
  5. */
  6. typedef struct dictht {
  7.  
  8. // 哈希表数组
  9. dictEntry **table;
  10.  
  11. // 哈希表大小
  12. unsigned long size;
  13.  
  14. // 哈希表大小掩码,用于计算索引值
  15. // 总是等于 size - 1
  16. unsigned long sizemask;
  17.  
  18. // 该哈希表已有节点的数量
  19. unsigned long used;
  20.  
  21. } dictht;

table是一个数组, 每个元素是一个指向dict.h/dictEntry 结构的指针.

哈希表节点

  1. /*哈希表节点*/
  2. typedef struct dictEntry {
  3. // 键
  4. void *key;
  5. // 值
  6. union {
  7. void *val;
  8. uint64_t u64;
  9. int64_t s64;
  10. } v;
  11. // 指向下个哈希表节点,形成链表
  12. struct dictEntry *next;
  13.  
  14. } dictEntry;

next属性指向下一个节点, 形成链表, 解决哈希冲突.

字典

  1. /*
  2. * 字典
  3. */
  4. typedef struct dict {
  5. // 类型特定函数
  6. dictType *type;
  7. // 私有数据
  8. void *privdata;
  9. // 哈希表
  10. dictht ht[];
  11. // rehash 索引
  12. // 当 rehash 不在进行时,值为 -1
  13. int rehashidx; /* rehashing not in progress if rehashidx == -1 */
  14. // 目前正在运行的安全迭代器的数量
  15. int iterators; /* number of iterators currently running */
  16. } dict;

type 和 privdata属性都是针对不同类型的键值对, 为创建多态字典设置.

  1. /*
  2. * 字典类型特定函数
  3. */
  4. typedef struct dictType {
  5. // 计算哈希值的函数
  6. unsigned int (*hashFunction)(const void *key);
  7. // 复制键的函数
  8. void *(*keyDup)(void *privdata, const void *key);
  9. // 复制值的函数
  10. void *(*valDup)(void *privdata, const void *obj);
  11. // 对比键的函数
  12. int (*keyCompare)(void *privdata, const void *key1, const void *key2);
  13. // 销毁键的函数
  14. void (*keyDestructor)(void *privdata, void *key);
  15. // 销毁值的函数
  16. void (*valDestructor)(void *privdata, void *obj);
  17. } 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设计与实现 (三): 字典的更多相关文章

  1. [Redis]Redis的设计与实现-链表/字典/跳跃表

    redis的设计与实现:1.假如有一个用户关系模块,要实现一个共同关注功能,计算出两个用户关注了哪些相同的用户,本质上是计算两个用户关注集合的交集,如果使用关系数据库,需要对两个数据表执行join操作 ...

  2. Redis学习笔记(三) 字典

    Redis的字典使用哈希表作为底层实现,一个哈希表中可以有多个哈希表节点,而每个哈希节点就保存在字典中的一个键值对. redis字典所用的哈希表由disht结构定义. typedef struct d ...

  3. Redis 设计与实现 4:字典

    Redis 中,字典是基础结构.Redis 数据库数据.过期时间.哈希类型都是把字典作为底层结构. 字典的结构 哈希表 哈希表的实现代码在:dict.h/dictht ,Redis 的字典用哈希表的方 ...

  4. Redis底层探秘(三):字典

    字典,又称为符号表(symbol table).关联数组(associative array)或映射(map),是一种用于保存键值对的抽象数据结构. 字典经常作为一种数据结构内置在很多高级编程语言里面 ...

  5. Redis设计与实现(一~五整合版)【搬运】

    Redis设计与实现(一~五整合版) by @飘过的小牛 一 前言 项目中用到了redis,但用到的都是最最基本的功能,比如简单的slave机制,数据结构只使用了字符串.但是一直听说redis是一个很 ...

  6. 《Redis设计与实现》读书笔记

    <Redis设计与实现>读书笔记 很喜欢这本书的创作过程,以开源的方式,托管到Git上进行创作: 作者通读了Redis源码,并分享了详细的带注释的源码,让学习Redis的朋友轻松不少: 阅 ...

  7. 《Redis设计与实现》

    <Redis设计与实现> 基本信息 作者: 黄健宏 丛书名: 数据库技术丛书 出版社:机械工业出版社 ISBN:9787111464747 上架时间:2014-6-3 出版日期:2014 ...

  8. 探索Redis设计与实现9:数据库redisDb与键过期删除策略

    本文转自互联网 本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutorial ...

  9. 探索Redis设计与实现6:Redis内部数据结构详解——skiplist

    本文转自互联网 本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutorial ...

随机推荐

  1. JAVA发送HttpClient

    http://bijian1013.iteye.com/blog/2310211 在发送HTTP请求的时候会使用到POST和GET两种方式,如果是传送普通的表单数据,我们直接将参数到一个Key-val ...

  2. shell检查网络出现异常、僵尸进程、内存过低后,自动重启

    #!/bin/bash while : do neterror=$(/bin/netstat -a | grep -cw "CLOSE_WAIT") echo "get ...

  3. jQuery单选框跟复选框美化

    在线演示 本地下载

  4. HTML5相册浏览插件

    在线演示 本地下载

  5. MarkDown初学者使用指南

    换MarkDown编辑器了,突然发现自己不会,尴尬!所以顺便总结下Markdown的常用语法 标题 一级标题(格式:#+XXXXX) 二级标题(格式:##+XXXXXX) 三级标题(格式:###+XX ...

  6. jquery知识location.search

    location.search在客户端获取Url参数的方法 location.search是从当前URL的?号开始的字符串如:http://www.baidu.com/s?wd=baidu&c ...

  7. AtCoder Regular Contest 102

    AtCoder Regular Contest 102 C - Triangular Relationship 题意: 给出n,k求有多少个不大于n的三元组,使其中两两数字的和都是k的倍数,数字可以重 ...

  8. mysql 一些属性

    1)定义id,设置int,涉及的属性有: BINARY二进制 UNSIGNED无符号数 UNSIGNED ZEROFILL 在列字段中使用UNSIGNED ZEROFILL属性,如: 插入int(4) ...

  9. JNI简单步骤01

    1.环境变量 1.1.相应的环境变量中,加入如下内容:(Windows) (1).ClASSPATH中输入 : ".;C:\Program Files\Java\jdk1.7.0_07\jr ...

  10. C-RAN

    无线接入网(RAN)是移动运营商赖以生存的重要资产.传统的无线接入网具有以下特点: 1. 每一个基站连接若干个固定数量的扇区天线,并覆盖小片区域,每个基站只能处理本小区收发信号: 2. 系统的容量是干 ...