《Redis设计与实现》读书笔记(二)

3.字典

  • C语言中没有内置字典,Redis数据库拿字典做为底层实现,须要构建字典结构及其增删查改API。在Redis中,字典的底层是哈希表,dictionary hash table。dictht定义以下。

    clipboard.png

  • 这里的table是一个数组,数组中每一个元素都是指向dictEntry的指针。dictEntry保存着键值对,其定义以下。

    clipboard.png

  • 上边字段中,含义或者做用比较模糊的就是*next指针了。这个字段的做用是解决键冲突的。示例以下。

    clipboard.png

  • 好,铺垫完了,开始进入字典结构。

    clipboard.png

  • 这里的每一个字段都有重要的做用。type和privdata指针支持了字典的多态。实现多态的原理:type为dictType结构的指针,而dictType则是保存了用于处理特定键值对的类型特定函数,privdata保存了须要传给类型特定函数的可选参数。

    clipboard.png

  • ht字段保存了两个哈希表,第一个表是正常使用,第二个则是rehash的时候使用。rehashidx字段也是rehash进度相关,没有进行rehash的时候,值为-1。完整的字典,普通状态下的示意图以下。

    clipboard.png

  • 添加键值对到字典的步骤:算法

    1. 根据键值对计算哈希值和索引值
    2. 根据索引值找到哈希表数组(dictEntry[])的指定索引
    3. 将键值对信息存放在dictEntry里边
  • 上边的三个步骤逻辑上存在一个问题——索引冲突!
  • 根据哈希算法的不一样,哈希碰撞的几率不一样。键值对A和键值对B被分配到相同的索引,怎么办!
  • 链地址法,这也就是dictEntry里边有个next指针的缘由了。后添加的会被添加到表头。示意图以下。

    clipboard.png

  • 至此,字典的功能实现基本完成,可是,工程实现尚未!什么意思?工程的意思是对字典的操做是持续不断的,大量的。这个时候就须要rehash,优化哈希表。好比,dictEntry数组的有些索引没有值,有些存在比较长的链。
  • 因此,从工程的角度考虑,rehash这个步骤必不可少。dict结构中有几个字段是用于rehash的。rehash的细节能够看原书或者别的资料。
相关文章
相关标签/搜索