Redis 数据结构之【字典】

含义:

       dict 是 Redis 服务器中出现最为频繁的复合型数据结构,除了 hash 结构的数据会用到字典外,整个 Redis 数据库的所有 key 和 value 也组成了一个全局字典,还有带过期时间的 key 集合也是一个字典。zset 集合中存储 value 和 score 值的映射关系也是通过 dict 结构实现的。

struct RedisDb {
     dict* dict; // all keys  key=>value
     dict* expires; // all expired keys key=>long(timestamp)
     ... 

 
struct zset {
     dict *dict; // all values  value=>score
     zskiplist *zsl;

内部结构 :

        dict 结构内部包含两个 hashtable,通常情况下只有一个 hashtable 是有值的。但是在 dict 扩容缩容时,需要分配新的 hashtable,然后进行渐进式搬迁,这时候两个 hashtable 存储的分别是旧的 hashtable 和新的 hashtable。待搬迁结束后,旧的 hashtable 被删除,新的 hashtable 取而代之。 

       所以,字典数据结构的精华就落在了 hashtable 结构上了。hashtable 的结构和 Java 的 HashMap 几乎是一样的,都是通过分桶的方式解决 hash 冲突。第一维是数组,第二维是链表。数组中存储的是第二维链表的第一个元素的指针。

 struct dictEntry {
     void* key;
     void* val;
     dictEntry* next; // 链接下一个 entry
 }
 struct dictht {
     dictEntry** table; // 二维
     long size; // 第一维数组的长度
     long used; // hash 表中的元素个数
     ...
 } 

使用:

  • map基础数据结构;
  • Redis 数据库所有 key 和 value;
  • 带过期时间的 key 的集合;
  • zset 中存储 value 和 scope 值的映射关系;
  • set 中(其中value 全部为 null);

渐进式 rehash:

       大字典的扩容是比较耗时间的,需要重新申请新的数组,然后将旧字典所有链表中的元素重新挂接到新的数组下面,这是一个 O(n)级别的操作,作为单线程的 Redis 表示很难承受这样耗时的过程。步子迈大了会扯着蛋,所以 Redis 使用渐进式 rehash 小步搬迁。愚公移山的精神。

       搬迁操作埋伏在当前字典的后续指令中(来自客户端的 hset/hdel 指令等),但是有可能客户端闲下来了,没有了后续指令来触发这个搬迁,那么 Redis 就置之不理了么?当然不会,优雅的 Redis 怎么可能设计的这样潦草。Redis 还会在定时任务中对字典进行主动搬迁。

hash 函数:

       hashtable 的性能好不好完全取决于 hash 函数的质量。hash 函数如果可以将 key 打散的比较均匀,那么这个 hash 函数就是个好函数。Redis 的字典默认的 hash 函数是 siphash。siphash 算法即使在输入 key 很小的情况下,也可以产生随机性特别好的输出,而且它的性能也非常突出。对于 Redis 这样的单线程来说,字典数据结构如此普遍,字典操作也会非常频繁,hash 函数自然也是越快越好。 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值