Redis中的Hash,结构以及渐进式rehash

Hash

哈希是一个键值对集合,可以将多个字段和值存储在同一个键中,便于管理一些关联数据,比如存储对象的属性。

使用场景:

商品详情:存储商品的各个属性,方便快速检索。

常用操作

hset key1:key2 field value
hget key1:key2 field
hmset key1:key2 field1 value1 field2 value2
hmget key1:key2 field1 field2
hdel key1:key2 field1
hincrby key1:key2 field num

实现

Hash类型的底层数据结构是由压缩列表或哈希表实现的:
● 如果哈希类型元素个数小于[512个(默认值,可由[hash-max-ziplist-entries)配置),所有值小于64」字节(默认值,可由[hash-max-ziplist-value」配置),Redis 会使用压缩列表作为Hash类型的底层数据结构
● 如果哈希类型元素不满足上面条件,Redis 会使用哈希表作为Hash 类型的底层数据结构。
在Redis7.0中,压缩列表数据结构已经废弃了,交由listpack数据结构来实现了。

redis中的HashTable

dict

字典dict

  1. type:指向dictType指针,保存了操作特定类型键值对的函数,Redis为不同用途的字典设置不同的类型特定函数。
  2. privdata:保存了需要传递给不同特定函数的可选参数。
  3. ht[2]:两个哈希表,字典使用的哈希表是ht[0],ht[1]则是当对ht[0]哈希表进行rehash时使用。
  4. rehashidx:记录当前rehash进度,没有进行rehash则为-1。

哈希表dictht

● table:哈希表实现存储元素的结构,可以看成是哈希节点(dictEntry)组成的数组。
● size:表示哈希表的大小。
● sizemask:这个是指哈希表大小的掩码,它的值永远等于 size-1,这个属性和哈希值一起约定了哈希节点所处的哈希表的位置,索引l的值 index= hash(哈希值)& sizemask。
● used:表示已经使用的节点数量。

渐进式rehash

扩容条件

我们先来说一下扩容,这里涉及到一个概念,即负载因子,redis 中 hash 的负载因子计算有一条公式:
负载因子=哈希表已保存节点的数量/哈希表的大小 = ht[0].used / ht[1].size

Redis 会根据负载因子的情况决定是否采取扩容:

  1. 负载因子大于等于1,这个时候说明空间非常紧张,新数据是在哈希节点的链表上找到的,这个时候如果服务器没有执行RDB快照或者AOF重写这两个持久化机制的时候,就会进行rehash 操作。
  2. 负载因子大于等于5,这个时候说明哈希冲突非常严重了,这个时候无论有没有进行 AOF 重写或者 RDB 快照,都会强制执行rehash 操作。

缩容:

当负载因子小于 0.1的时候,就会进行缩容操作。这个时候新表大小是老表的 used 的最近的一个 2 次方幂。例如老表的 used =1000,那么新表的大小就是1024。如果没有执行RDB 快照和 AOF重写的时候就会进行缩容,反之不会进行。

扩容过程

  1. 为ht[1]分配空间,让字典同时持有ht[0]和ht[1]两个哈希表。
  2. 在字典中维持一个索引计数器变量rehashidx,并将它的值设置为0,表示rehash工作正式开始。
  3. 在rehash进行期间,每次对字典执行CRUD:添加、删除、查找或者更新操作时,程序除了执行指定的操作以外,还会顺带将ht[0]哈希表在rehashidx索引上的所有键值对rehash到ht[1],当rehash工作完成之后,程序将rehashidx+1(表示下次将rehash下一个桶)。
  4. 随着字典操作的不断执行,最终在某个时间点上,ht[0]的所有键值对都会被rehash至ht[1],这时程序将rehashidx属性的值设为-1,表示rehash完成。

渐进式rehash的好处:

在于它采取分而治之的方式,将rehash键值对所需的计算工作均摊到对字典的每个添加、删除、查找和更新操作上,从而避免了集中式rehash 而带来的庞大计算量。
在迁移过程中,读写操作是怎样的?
在迁移时,首先会从ht[0]读取数据,如果ht[0]读不到,则会去ht[1]读。
迁移过程中,新增的数据只会存在ht[1]中,而不会存放到ht[0],ht[0]只会减少不会新增。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值