http://redisbook.com/index.html

rehash

随着操作的不断执行, 哈希表保存的键值对会逐渐地增多或者减少, 为了让哈希表的负载因子(load factor)维持在一个合理的范围之内, 当哈希表保存的键值对数量太多或者太少时, 程序需要对哈希表的大小进行相应的扩展或者收缩。

扩展和收缩哈希表的工作可以通过执行 rehash (重新散列)操作来完成, Redis 对字典的哈希表执行 rehash 的步骤如下:

  1. 为字典的 ht[1] 哈希表分配空间, 这个哈希表的空间大小取决于要执行的操作, 以及 ht[0] 当前包含的键值对数量 (也即是 ht[0].used 属性的值):

    • 如果执行的是扩展操作, 那么 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[0] , 将 ht[1] 设置为 ht[0] , 并在 ht[1] 新创建一个空白哈希表, 为下一次 rehash 做准备。

举个例子, 假设程序要对图 4-8 所示字典的 ht[0] 进行扩展操作, 那么程序将执行以下步骤:

  1. ht[0].used 当前的值为 4 , 4 * 2 = 8 , 而 8 (2^3)恰好是第一个大于等于 4 的 2 的 n 次方, 所以程序会将 ht[1] 哈希表的大小设置为 8 。 图 4-9 展示了 ht[1] 在分配空间之后, 字典的样子。
  2. 将 ht[0] 包含的四个键值对都 rehash 到 ht[1] , 如图 4-10 所示。
  3. 释放 ht[0] ,并将 ht[1] 设置为 ht[0] ,然后为 ht[1] 分配一个空白哈希表,如图 4-11 所示。

至此, 对哈希表的扩展操作执行完毕, 程序成功将哈希表的大小从原来的 4 改为了现在的 8 。

哈希表的扩展与收缩

当以下条件中的任意一个被满足时, 程序会自动开始对哈希表执行扩展操作:

  1. 服务器目前没有在执行 BGSAVE 命令或者 BGREWRITEAOF 命令, 并且哈希表的负载因子大于等于 1 ;
  2. 服务器目前正在执行 BGSAVE 命令或者 BGREWRITEAOF 命令, 并且哈希表的负载因子大于等于 5 ;

其中哈希表的负载因子可以通过公式:

# 负载因子 = 哈希表已保存节点数量 / 哈希表大小
load_factor = ht[0].used / ht[0].size

计算得出。

比如说, 对于一个大小为 4 , 包含 4 个键值对的哈希表来说, 这个哈希表的负载因子为:

load_factor = 4 / 4 = 1

又比如说, 对于一个大小为 512 , 包含 256 个键值对的哈希表来说, 这个哈希表的负载因子为:

load_factor = 256 / 512 = 0.5

根据 BGSAVE 命令或 BGREWRITEAOF 命令是否正在执行, 服务器执行扩展操作所需的负载因子并不相同, 这是因为在执行 BGSAVE 命令或 BGREWRITEAOF 命令的过程中, Redis 需要创建当前服务器进程的子进程, 而大多数操作系统都采用写时复制(copy-on-write)技术来优化子进程的使用效率, 所以在子进程存在期间, 服务器会提高执行扩展操作所需的负载因子, 从而尽可能地避免在子进程存在期间进行哈希表扩展操作, 这可以避免不必要的内存写入操作, 最大限度地节约内存。

另一方面, 当哈希表的负载因子小于 0.1 时, 程序自动开始对哈希表执行收缩操作。

Redis之rehash操作相关推荐

  1. 【Redis高频面试题系列】:说说Redis的rehash过程

    Redis的字典由 dict.h/dict 结构如下(rehash的重点) typedef struct dict {//类型特性函数dictType *type;//私有数据void *privda ...

  2. redis渐进式rehash机制

    在Redis中,键值对(Key-Value Pair)存储方式是由字典(Dict)保存的,而字典底层是通过哈希表来实现的.通过哈希表中的节点保存字典中的键值对.我们知道当HashMap中由于Hash冲 ...

  3. redis的hash操作在集中式session中的应用

    在集群部署时,为了高可用性的目的,往往把session进行共享,共享分为两种:session复制和集中式管理. redis在session集中式管理中可以起到比较大的作用. 制约session集中式共 ...

  4. Spring Boot 整合 Redis 实现缓存操作

    摘要: 原创出处 www.bysocket.com 「泥瓦匠BYSocket 」欢迎转载,保留摘要,谢谢! 『 产品没有价值,开发团队再优秀也无济于事 – <启示录> 』 本文提纲 一.缓 ...

  5. Redis String 类型操作及常用命令

    七个原则 Redis 是一个操作数据结构的语言工具,它提供基于 TCP 的协议以操作丰富的数据结构.在 Redis 中,数据结构这个词的意义不仅表示在某种数据结构上的操作,更包括了结构本身及这些操作的 ...

  6. Redis set 类型操作及常用命令

    七个原则 Redis 是一个操作数据结构的语言工具,它提供基于 TCP 的协议以操作丰富的数据结构.在 Redis 中,数据结构这个词的意义不仅表示在某种数据结构上的操作,更包括了结构本身及这些操作的 ...

  7. Redis Hash 类型操作及常用命令

    七个原则 Redis 是一个操作数据结构的语言工具,它提供基于 TCP 的协议以操作丰富的数据结构.在 Redis 中,数据结构这个词的意义不仅表示在某种数据结构上的操作,更包括了结构本身及这些操作的 ...

  8. Redis List 类型操作及常用命令

    七个原则 Redis 是一个操作数据结构的语言工具,它提供基于 TCP 的协议以操作丰富的数据结构.在 Redis 中,数据结构这个词的意义不仅表示在某种数据结构上的操作,更包括了结构本身及这些操作的 ...

  9. 基于 Redis 实现 CAS 操作

    基于 Redis 实现 CAS 操作 Intro 在 .NET 里并发情况下我们可以使用 Interlocked.CompareExchange 来实现 CAS (Compare And Swap) ...

最新文章

  1. 微信公众号开发本地环境开发_如何在5分钟内使HTTPS在本地开发环境上工作
  2. 自定义监听器 java
  3. 黔农云认证用别人认证_绝对干货,黔农云常见17个问题答疑!
  4. Pandas 基础(8) - 用 concat 组合 dataframe
  5. 使用Dezender对zend加密后的php文件进行解密
  6. 前端图片上坐标连线_前端图形学(十三)——弹跳运动的深入之傲娇的小球
  7. 量化信噪比 非均匀量化_达尔优EM910牧马人轻量化游戏鼠标拆解评测
  8. python第一题 引发的思考和学习
  9. 【TO DO!】二分查找各种情况大总结
  10. RejectedExecutionException 分析
  11. android控件缩放后居中,三大布局的基本摆放属性总结,以及imageVIew图片摆放的缩放问题...
  12. WinRAR去除打开后弹出广告的方法
  13. linux vga 分辨率低,通过 VGA 接口连接显示器时分辨率不正确
  14. java中美元符号的作用_MyBatis中#号与美元符号的区别
  15. 研究意识问题为什么如此困难
  16. 19.Eager模式
  17. 程序员必备的11个Github优质项目
  18. ListView数据动态刷新
  19. 一个Java初学者的体验
  20. 香港四日,逛吃逛吃—16家地道美味全纪录+伴手礼推荐

热门文章

  1. 重拾Javascript(四) 运动 图片的淡入淡出
  2. fabric-ca 登记身份时报Error: Response from server: Error Code: 20 - Authentication failure
  3. Android之使用MediaMetadataRetriever类获取视频第一帧
  4. 32 - I. 从上到下打印二叉树
  5. 无法解析的外部符号+_mysql_fetch_row_vs连接mysql出现以下错误,求解答,谢谢,不胜感激...
  6. Cookie知识总结(-)
  7. outlook express重定向
  8. 通过ANT实现jmeter批量执行脚本、生成报告、发送邮件全套build.xml文件
  9. subsonic 配置及使用
  10. Chrome Beta for MacLinux正式发布下载