字典(Hash)

Redis的字典是使用HashTable作为底层实现,一个哈希表存储多个键值对节点。

字典结构

typedef struct dict {//类型特定函数dictType *type;//私有数据void *private;//哈希表dictht ht[2];//rehash索引in trehashidx;//当没有进行rehash时,为-1
} dict;
  • type是一个在指向dictType结构的指针,每个dictType结构保存了一簇用于操作特定键值对的函数,该字段是为多态字典做准备。
  • private属性保存了需要传给dictType中函数的可选参数。
  • ht是一个包含两个项的哈希表的数组,当rehash时需要用到第二个作临时存储

Hash表结构

typedef struct dictht {//哈希表数组dictEntry **table;//哈希表大小unsigned long size;//哈希表大小掩码, 用于计算索引值//总是等于size - 1unsigned long sizemask;//该哈希表已有节点的数量unsigned long used;
} dictht;

table 是一个数组,数组中每个元素都是一个指向哈希表节点(dictEntry)结构的指针。

Hash表节点结构

typedef struct dictEntry {//键void *key;//值union{void *val;//可以是指针uint64_tu64;//无符号整数int64_ts64;//带符号整数} v;//指向下个哈希表节点,形成链表(解决哈希冲突)struct dicEntry *next;
} dictEntry;

三者关系

字典------>哈希表------>哈希表节点

哈希算法

下面的代码解释了字典如何根据key计算索引值index

//1、使用字典设置的哈希函数,计算键key的哈希值
hash = dict->type->hashFunction(key)
//2、根据hash值与哈希表掩码相与得到索引值
index = hash & dict->ht[x].sizemask;

解决哈希冲突

当不同的键被分配到同一个哈希表数组索引上(哈希冲突),redis采用链地址法来解决,每一个哈希节点都有一个*next指针,用了指向下一个哈希节点。

  • 因为没有一个指向链表尾结点的指针,所以哈希表采用头插入的方式(时间复杂度为O(1)),将新插入的节点插在其他链表节点的首部(如下两图)。


rehash

负载因子==ht[0].used/ht[0].size

  • 什么时候会执行哈希表的扩展与收缩?

    当以下条件之一满足时,会对哈希表进行扩展操作

    • 服务器没有在执行bgsave(用于在后台异步保存当前数据库的数据到磁盘)与bgrewriteaof(用于异步执行一个 AOF(AppendOnly File) 文件重写操作)命令时,并且哈希表的负载因子大于等于1
    • 服务器正在执行bgsave与bgrewriteaof命令,并且哈希表的负载因子大于5(因为每一个哈希表数组节点可能存在大于一个节点,所以会大于1)

    当哈希表的负载因子小于0.1时,程序自动开始对哈希表执行收缩

  • 如何执行哈希表的扩展与收缩?

    • 为字典的ht[1]分配内存空间,大小取决于ht[0]的大小,计算如下

      • 如果执行的是扩展操作,ht[1]的大小为第一个大于等于ht[0].used*22^n(2的n次方幂)

      • 如果执行的是收缩操作,ht[1]的大小为第一个大于等于ht[0].used2^n(2的n次方幂)


  • 将保存在ht[0]上的所有键值对重新计算哈希值(rehash)放到ht[1]上

  • 迁移完成后,释放ht[0]并将ht[1]设置为ht[0],并新建一个ht[1]空白哈希表为下一次rehash做准备

  • rehash并不是一次完成的,而是渐进式完成,步骤如下

  • 为ht[1]分配空间,字典同时持有ht[0]和ht[1]两个哈希表

  • 在字典中位置索引计数器变量rehashix,将他的值设置为0

  • 在rehash期间,每次对字典执行添加、删除、查找或者更新操作时,程序出了执行指定的操作之外,还会将ht[0]在rehashidx索引上的所有键值对rehash到ht[1],完成后将rehashidx自增1

  • 当某个时间点上ht[0]的所有键值对都被rehash成功,程序将rehashidx设为-1

rehash过程中,字典会同时使用两个哈希表,删除,查找,更新操作会在两个表中查找,新增则会直接更新到ht[1]


该文章是学习《redis设计与实现》的读书笔记,如有错误或模糊点请在评论区指针,共同进步共同学习!

redis的字典(Hash)相关推荐

  1. Redis数据结构为字典Hash 实践 之 系统数据字典实时触发缓存存储

    一.项目用redis-learn,文章参考 Hash底层存储数据的方式确实跟其他数据结构有点不同,其他数据结构几乎都是:Key-Value的存储,而Hash则是:Key – [Field-Value] ...

  2. Redis数据结构为字典Hash 的 存储、获取、删除等的操作

    一.项目用redis-learn,文章参考 Hash底层存储数据的方式确实跟其他数据结构有点不同,其他数据结构几乎都是:Key-Value的存储,而Hash则是:Key – [Field-Value] ...

  3. Redis 数据结构-字典源码分析

    2019独角兽企业重金招聘Python工程师标准>>> 相关文章 Redis 初探-安装与使用 Redis 数据结构-字符串源码分析 本文将从以下几个方面介绍 前言 字典结构图 字典 ...

  4. 深入redis内部--字典实现

    redis的字典定义和实现在dict.h和dict.c文件中. 1.字典结构 typedef struct dict { dictType *type; //定义了字典需要的函数 void *priv ...

  5. Redis之字典(hashtable)

    Redis之字典 字典是什么(hashtable) 总体结构 dict dictht(散列表) dictEntry 如何解决哈希冲突 1. 链表法 2.rehash法 字典是什么(hashtable) ...

  6. Python操作Redis中的hash

    Redis 数据库hash数据类型是一个string类型的key和value的映射表,适用于存储对象.Redis 中每个 hash 可以存储 232 - 1 键值对(40多亿).  Python的re ...

  7. redis中的hash扩容渐进式rehash过程

    背景: redis字典(hash表)当数据越来越多的时候,就会发生扩容,也就是rehash 对比:java中的hashmap,当数据数量达到阈值的时候(0.75),就会发生rehash,hash表长度 ...

  8. Redis的字典扩容与ConcurrentHashMap的扩容策略比较

    本文介绍Redis的字典(是种Map)扩容与ConcurrentHashMap的扩容策略,并比较它们的优缺点. (不讨论它们的实现细节) 首先Redis的字典采用的是一种''单线程渐进式rehash' ...

  9. Redis 哈希(Hash)

    为什么80%的码农都做不了架构师?>>>    Redis hash 是一个string类型的field和value的映射表,hash特别适合用于存储对象. Redis 中每个 ha ...

最新文章

  1. Python之collections容器数据类型
  2. [BUUCTF-pwn]——wdb_2018_2nd_easyfmt
  3. 百度富文本编辑器的应用技巧---在一个页面中使用多个样式不同功能不同的编辑器...
  4. django 1.8 官方文档翻译: 2-4-3 模式编辑器
  5. 008 查看套接字选项是否受支持(获取当前环境下套接字选项默认值)
  6. 设置HttpClient的授权标头
  7. 2017 ACM-ICPC北京网络赛: C. Matrix(DP)
  8. 相机模型与标定(十二)--opencv圆形标志点检测算法
  9. iOS测试和Android测试的区别
  10. 成本更低、更优观看体验——自研S265编解码器解析
  11. jpg转word免费的软件
  12. 中级计算机软件师考试试题,计算机水平考试-(a)中级软件设计师下午试题模拟64.doc...
  13. 热门好用的二维码生成器API
  14. 审计一波appcms-持续更新。
  15. DBeaver 驱动安装
  16. 笔记 C++11 std::minmax_element() 的使用(寻找最小值和最大值)
  17. 高效的APP在线制作平台,让梦想轻松孵化器
  18. 模拟豆机、高尔顿瓶【java】
  19. 学渣的刷题之旅 leetcode刷题 27.移除元素
  20. S40手机上的来电防火墙

热门文章

  1. S5PV210开发 -- TTL和CMOS电平
  2. 毕业论文格式要求 题注修改
  3. JS判断字符是否为数字类型
  4. 通过枚举驱动符号链接 判断程序***有几个实例在运行
  5. 正则表达式学习及小练习
  6. Fortran和C/C++混合编程学习笔记(一):编译链接
  7. \u, \x,0x区别
  8. 明日方舟公式计算机,明日方舟公开招募公式汇总
  9. php网站设计文档,企业门户网站设计与实现(word文档)最新版
  10. POJO,PO,JAVABEAN