• 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的操作分摊到每次的数据库操作上。

  • 相关阅读:
    数据库压力测试的参考地址
    Infopath表单部署到Farm的方法
    oracle 的几个开发工具比较
    智能Web算法/NLP 参考图书
    Wireshark & Ethereal包分析工具【图书节选】
    Sharepoint内置的”翻译管理库”体验
    开发相关“视频公开课webcast”资源地址
    读书:架构师的12项技能 12 ESSENTIAL SKILLS FOR SOFTWARE ARCHITECTS
    Linux 下Oracle Client JAVA JDBC 集成点滴
    MOS2010的界面介绍和定制方法简介【资料汇集】
  • 原文地址:https://www.cnblogs.com/sylz/p/6937365.html
Copyright © 2020-2023  润新知