redis 的渐进式 rehash,为什么 java 不采用渐进式 rehash

6 篇文章 0 订阅
4 篇文章 0 订阅

redis 的渐进式 rehash,为什么 java 不采用渐进式 rehash

说明

  1. @author JellyfishMIX - github / blog.jellyfishmix.com
  2. LICENSE GPL-2.0
  3. 本文默认已了解 jdk 1.8 HashMap 的 rehash 机制。

redis 的 dict

  1. redis 的 dict 是一个用于维护 key 和 value 映射关系的数据结构,与很多语言中的 Map 或 Dictionary 类似。redis 的一个 database 中所有 key 到 value 的映射,就是用一个 dict 来维护的。dict 本质上是为了解决算法中的查找问题(search)。
  2. 一般查找问题的解法分为两个大类:一个是基于各种平衡树,一个是基于哈希表,平常使用的各种 Map 或 Dictionary,大多是基于哈希表实现的。当然 jdk 1.8 中 HashMap 使用了哈希表 + 链表/红黑树的组合进行了优化,但本质上还是哈希表。
  3. redis 的 dict 也是一个基于哈希表的数据结构。

redis 渐进式 rehash

  1. redis dict 存在两个数组 ht[0], ht[1]。扩容和收缩的时候,如果 dict 中有很多元素,一次性将这些键从 ht[0] 全部 rehash 到 ht[1] 的话,期间一直在处理 rehash 的工作,可能会导致 dict 较长时间不可用,无法对外提供服务。所以,redis 采用渐进式 rehash 的方式。

  2. 在字典中维持一个索引计数器变量 rehashidx,它的值为 -1 表示 rehash 没有开始。将 rehashidx 的值设置为0,表示 rehash 工作开始。每次的增删改查,rehashidx + 1,然后执行原 hash 表 rehashidx 索引位置的 rehash。

  3. 这样 rehash 的消耗分摊在每一次对 dict 的访问中,避免集中式 rehash 带来的庞大计算量导致服务一段时间内不可用。

java 不采用渐进式 rehash 的原因

渐进式 rehash 看起来很好,为什么 java 的 HashMap 不采用这样渐进式 rehash?

时间开销

  1. HashMap 一般作为局部变量用的多,即生命周期是仅在一次方法的调用中。如果是 web 应用,很多 HashMap 的生命周期仅在本次请求内。
  2. 渐进式 rehash 比集中式 rehash 整体上多了额外的计算开销。这样渐进式 hash 会让作为局部变量的 HashMap rehash 总耗时增加,进而导致本次方法调用耗时增加。
  3. HashMap 用作局部变量的场景是最多的,这种情况下,渐进式 rehash 耗时都是这这一次方法调用内。如果是 web 应用,局部变量的渐进式 rehash 耗时会叠加在本次请求内。由于渐进式 rehash 带来的额外计算开销,渐进式 reahsh 会比集中式 rehash 整体耗时长。没有优化,反而是一种负担。
  4. 虽然一些框架把 HashMap 用作共享变量,生命周期可能会像 redis 的 dict 一样,在整个应用的生命周期中。但是 HashMap 用到最多的地方还是局部变量,不能为了少量框架里的 HashMap,被迫让局部变量的 HashMap 变成渐进式 rehash。

空间开销

空间开销上,渐进式 rehash 可预见性地增加了很多内存消耗,因为很长一段时间内要维护两个数组。

总结

渐进式 rehash 只适合用在作为共享变量的哈希表中,且多次方法调用(特别是多次请求)都会去操作这个共享变量。这样才能发挥其 rehash 耗时每次调用均分的优势。比如 redis 的 dict 就是很好的例子。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JellyfishMIX

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值