redis基本数据类型——③哈希(字典)

hash(字典)(hset,hget,hlen,hmset 批量set,hincrby 自增)

  • Redis 的字典相当于 Java 中的 HashMap。
  • Redis 的字典与 HashMap 的相同点:无序,采用的数组 + 链表的结构,数组位置碰撞时,将碰撞的元素使用链表串接起来。
  • 不同点:Redis 字典的值只能是字符串,而 HashMap 的值可以是多种类型。另外它们 rehash 的方式不一样,因为 HashMap 在字典很大时,一次性全部 rehash 会是一个很耗时的操作,Redis 为了高性能,不能堵塞服务,所以采用了渐进式 rehash 的策略。渐进式 rehash 就是同时保留旧数组和新数组,在后续对 hash 的操作中渐渐的将旧数组中的数据迁移到新数组中,所以在操作处于 rehash 过程的字典时,需要同时访问新旧两个数组,如果在旧数组中找不到元素,就需要去新数组中查找。
  • redis 中每个字典都带有两个哈希表:ht[0] 和 ht[1],平时使用的是ht[0],ht[1] 只在进行 rehash 时使用。
  • redis的哈希表是如何解决冲突的?:它采用链地址法来解决键冲突的问题,每个哈希表节点都有一个next指针指向另一个哈希表,通过这个next指针将两个索引值相同的键连接起来。

字典rehash的步骤:(通过 rehash 操作来扩展或收缩哈希表)

  1. 为字典的 ht[1] 哈希表分配空间,这个空间大小取决于要执行的操作,以及 ht[0] 当前包含的键值对数量,也就是 ht[0].used 的值,used 记录哈希表已有的键值对数量,如果执行的是扩展操作,那么 ht[1] 的大小为第一个大于等于 ht[0].used x 2 的 2n ;如果执行的是收缩操作,那么 ht[1] 的大小为第一个大于等于 ht[0].used 的 2n
  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 做准备。

渐进式rehash的原理(步骤)

  1. 为 ht[1] 分配空间,让字典同时持有 ht[0] 和 ht[1] 两个哈希表。
  2. 在字典中维持一个索引计数器 rehashidx,值设为0,表示开始 rehash 操作。
  3. 在 rehash 期间,每次对字典执行添加、删除、查找或更新操作时,程序会将 ht[0] 哈希表在索引上的键值对 rehash 到 ht[1] ,并将索引值加1。
  4. 随着字典操作的不断执行,最终 ht[0] 的所有键值对都会被 rehash 到 ht[1] ,然后将索引值设为 -1,表示 rehash 操作完成。
发布了307 篇原创文章 · 获赞 11 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/dl674756321/article/details/103939521
今日推荐