zoukankan      html  css  js  c++  java
  • Redis的设计与实现——字典

    参考博客

    绝大多数语言中的字典底层实现基本上都是哈希表。哈希表中用 “负载因子” 来衡量哈希表的 空/满 程度。为了让负载因子在一定的合理范围之内,提高查询的性能,一般的做法是让哈希表扩容,然后rehash一把。

    but,扩容也不一定就能解决负载因子过大的问题。Redis作为一款成熟的非关系型数据库,肯定有他的独到解决办法!!!能够保证rehash是有效的。

    讲解rehash之前看下redis里面的一些数据结构:字典的底层有哈希表实现,ht存放的是哈希表。

    Redis对字典的rehash的步骤如下:

      ①为字典的ht[1]分配空间,空间的大小取决于要执行的操作(扩展还是收缩)以及ht[0]的used属性。

        扩展:ht[1]的大小为   第一个大于等于  ht[0].used*2  的 2n

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

      ②将ht[0]里面的键值对rehash到ht[1]。

      ③都迁移到ht[1]之后,释放ht[0],将ht[1]设置为ht[0],然后在ht[1]新建空白哈希表。为下一次rehash做准备。

    写道这里,我还是没有搞清楚这个redis的哈希设计高效在哪里?直到我看到了渐进式hash!!!

    渐进式hash

    何为渐进式hash?在上面提到的rehash中,不是一次性将ht[0]的数据送入ht[1],如果数据量过大,将会严重影响redis数据库的性能,所以采用了一种方法渐进式。

    渐进式具体操作呢?

      ①给ht[1]分配空间,让字典同时持有两个哈希表ht[0]和ht[1]。

      ②利用一个巧妙地数据设计,rehashidx,初值设为-1,表示不需要rehash;一旦需要rehash的时候,设置为0,表示rehash工作正式开始。

      ③在rehash进行期间,除了执行指定的操作(增删改查)之外,还会附加做一些工作,就是将ht[0]上的rehashidx对应的所有键值对rehash到ht[1]上,移完之后,rehashidx加1.

      ④随着字典操作(增删改查)的不断执行,最终会在某个时间点上,ht[0]的所有键值对都会被rehash到ht[1]上,这时程序将rehashidx设置为-1,表示rehash操作已全部完成。rehash的过程中,添加操作只会在ht[1]上进行,这样能够保证ht[0]的键值对只减不增。

    渐进式rehash操作的好处是,避免了集中式rehash操作,将rehash的操作分摊到每次的数据库操作上。

  • 相关阅读:
    c3p0死锁
    空间分析过程
    UUID.randomUUID().toString() 的作用
    ajax做的一些总结
    vue3组合式api
    引入高德地图
    高德地图做标记
    页面刷新回到顶部
    高德地图如何只显示中国地图,不显示国外地图
    vue使用高德地图错误 ‘AMapUI‘ is not defined , ‘AMap‘ is not defined 问题及解决。
  • 原文地址:https://www.cnblogs.com/sylz/p/6937365.html
Copyright © 2011-2022 走看看