使用场景:

# set person name "tom"

# set person name "jerry"

1. 字典结构:

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

哈希表节点数据结构typedef struct dictEntry {//键void *key;//值
    union {        //值可以是一个指针void *val;//也可以是一个uint64_t整数uint64_tu64;//也可以是int64_t整数int64_ts64;} v;//指向下个哈希表节点,形成链表,用来使用拉链法解决哈希冲突struct dictEntry *next;} dictEntry;

字典数据结构typedef struct dict {//类型特定函数(保存了一些操作特定类型键值对函数)dictType *type;//私有数据(保存了传给特定函数的一些参数)void *privdata;//哈希表(一般使用ht[0]哈希表,ht[1]是在rehash时使用)dictht ht[2];//rehash 索引(记录了rehash的进度,不rehash时,值为-1)int trehashidx;} dict;

2. 哈希算法:

当添加一个新键值时,会先根据键计算出哈希值和索引值,然后将新键值节点放到指定索引上(dictEntry*[index])。

计算哈希值:hash = dict -> type -> hashFunction(key);

计算索引值:index = hash & dict -> ht[x].sizemask;

3. 解决哈希冲突:

当键冲突时,使用next指针将新键连接起来。注意:为了速度考虑,程序会将新节点添加到链表的表头位置。

4. rehash:

随着数据的增多和减少,为了让哈希表的负载因子维持在一个合理的范围,需要对哈希表进行扩展和收缩。

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

rehash扩展触发条件:

1). 服务器目前没有在执行BGSAVE命令或者BGREWRITEAOF命令,并且负载因子大于等于1。

2). 服务器目前正在执行BGSAVE命令或者BGREWRITEAOF命令,并且负载因子大于等于0.5。

rehash收缩触发条件:负载因子小于0.1。

步骤如下:

1). 在没有rehash时,字典只使用ht[0]。在rehash时,程序会对ht[1]分配空间。

扩展:ht[1]的大小为第一个大于等于ht[0].used * 2的2^n (2的n次方幂);

收缩:ht[1]的大小为第一个大于等于ht[0].used的2^n;

2).  将ht[0]的所有数据全部rehash到ht[1]上面,rehash指的是重新计算键的哈希值和索引值,然后放到ht[1]的指定位置上。

3). 当ht[0]上的数据全部迁移到ht[1]后,释放ht[0],将ht[1]置为ht[0],并在ht[1]上新建一个空的哈希表,为下一次rehash做准备。

5.  渐进式rehash(rehash的优化,触发条件由负载因子决定,如上)

当哈希表的键值对数量巨大时,一次rehash会非常耗时,为了避免对服务器性能造成影响,服务器采用分批次、渐进式的将ht[0]里面的键值对慢慢的rehash到ht[1]。

步骤:

1)为ht[1]分配空间,字典同时持有ht[0]和ht[1]。

2)字典中设置一个计数器rehashidx,当值为0时,表示rehash开始。

3)在rehash期间,每次增删改查时,程序还会顺带将ht[0]在rehashidx索引上的所有键值对rehash到ht[1],当rehash完成后,rehashidx增一。(这里是将table上对应的某条索引值指向的数据节点链表迁移到ht[1]中,th[0].table[rehashidx]数据就空了)

4)随着操作的不断执行,ht[0]上的所有键值对都会被rehash到ht[1]上,这时rehashidx为-1,表示rehash完成。

注意:

1)在rehash执行期间,新数据会保存到ht[1]里面,而ht[0]不进行添加操作,这样,ht[0]里的数据会逐渐迁移到ht[1],直到ht[0]清空。

2)在rehash执行期间,查找某个键时,会先从ht[0]中查找,如果没找到就去ht[1]里面查找。

转载于:https://www.cnblogs.com/wwzyy/p/10615939.html

Redis数据结构:字典(hash表)相关推荐

  1. Redis数据结构-SkipList(跳表)

    Redis数据结构-SkipList(跳表) SkipList(跳表)首先是链表,但与传统链表相比有几点差异: 元素按照升序排列存储 节点可能包含多个指针,指针跨度不同. 查找19时 可见效率会比较高 ...

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

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

  3. Redis数据结构之——hash

    写在前面 以下内容是基于Redis 6.2.6 版本整理总结 一.Redis 数据结构hash的编码格式 Redis中hash数据类型使用了两种编码格式:ziplist(压缩列表).hashtable ...

  4. Redis数据结构——字典-hashtable

    字典简介: 字典,又称为符号表(symbol table).关联数组(associative array)或映射(map),是一种用于保存键值对的抽象数据结构. 字典是一种用于保存键值对的抽象数据结构 ...

  5. [redis数据结构]之 hash类型

    在讲解语法知识之前,教你如何掌握各种hash的基本潜规则,在不同的语言中,有点称之为hash.有的是map,但不管这么样,hash你可以看作是key-value一组的集合.我先将java中map的概念 ...

  6. 【数据结构bull;hash表】重排九宫…

    [数据结构•hash表]重排九宫 Time Limit:10000MS  Memory Limit:65536K Total Submit:47 Accepted:15 Description 我先来 ...

  7. Redis数据结构之hash

    对象类数据的存储如果具有较频繁的更新需求操作会显得笨重,这里我们可以用redis的hash数据类型解决. 一.hash类型 新的存储需求:对一系列存储的数据进行编组,方便管理,典型应用存储对象信息 需 ...

  8. Redis数据结构之——跳表skiplist

    写在前面 以下内容是基于Redis 6.2.6 版本整理总结 一.跳表(skiplist) 如何理解跳表?在了解跳表之前,我们先从普通链表开始,一点点揭开跳表的神秘面纱~ 首先,普通单链表来说,即使链 ...

  9. redis数据结构hash

    Redis数据结构之hash Hash存储结构 Hash是一个string 类型的field和value的映射表.Hash特别适合存储对象,相对于将对象的每个字段存成单个string 类型.一个对象存 ...

  10. Redis数据结构-对象

    目录 前言 1.对象的类型与编码 1.1.类型 2.编码和底层实现 2.1.字符串对象 2.2.列表对象 2.3.哈希对象 2.4.集合对象 2.5.有序集合对象 参考 最后 前言 Redis并没有直 ...

最新文章

  1. Hadoop集群中运行MapReduce程序错误记录
  2. java构造器_Java构造器就是这么简单!
  3. P91--商品保存debug完成
  4. arm中断保护和恢复_嵌入式ARM系统异常和中断处理知识总结
  5. oracle删除临时表空间语句,Oracle中临时表空间的清理
  6. nodejs通过later实现定时执行任务
  7. 性能测试 查看Android APP 帧数FPS的方法
  8. 软件系统的沙盘测试是什么东西,沙盘(一款安全软件)_百度百科
  9. [CVE-2021-45105] Apache Log4j2 漏洞复现与原理详细分析
  10. 10.3注意力的评价函数
  11. #创新应用#飞流下载:下载娱乐两不误
  12. 2022-2028全球光纤束行业调研及趋势分析报告
  13. 使用ul li 实现图片的左右滚动
  14. JDK8 到 JDK17 各个版本的重要特性一览
  15. 网吧服务器软件维护合同范本,网吧电脑维护合同范本
  16. Go实战--golang中使用Goji微框架(Goji+Mongodb构建微服务)
  17. 应届生去软通动力怎么样_应届生第一份工作应该怎么找?
  18. /tmp/cc8TKj9o.s: Assembler messages
  19. 从学生表中查询每门课都是80分以上的学生的学号与姓名。
  20. 一起做RGB-D SLAM 学习笔记(2)

热门文章

  1. LeetCode 98验证二叉搜素树(中序遍历)99恢复二叉搜索树
  2. 操作系统之磁盘调度——SCAN实例讲解
  3. Python3算法基础练习:编程100例( 21~ 25)
  4. 数据结构之快速排序图文详解及代码(C++实现)
  5. ECMAScript6入门教程(一)
  6. SpringMVC中@ResponseBody和@RequestBody的使用
  7. Java-Web Servlet开发
  8. Oracle 段区块 分配 (2)
  9. 剑指Offer #14 链表中倒数第k个结点(快慢指针) | 图文详解
  10. 5去掉button按钮的点击样式_CSS实现复古按钮