Redis 字典的实现(2)
2015-06-27 15:47
726 查看
1.Redis 字典 Hash算法
根据key计算hash值
hash = dict -> type -> hashFunction(key);
根据sizemask属性和哈希值,计算出索引,ht[x]可以是ht[0]或ht[1]
index = hash & dict -> ht[x].sizemask;
Redis使用MurmurHash2算法计算键的哈希值,优点在于即使输入的键是有规律的,算法仍能给出一个很好的随机分布性。
2.解决Hash冲突
当2个或多个不同对象的Hash值相同时,会被分配到哈希表的同一个索引上,此时就称之为哈希冲突。
Redis采用链地址法解决键冲突,每个哈希节点都有一个next指针,由此指针构成一个单向链表,新添加的元素在链表表头。
3.rehash
负载因子 = 哈希表节点数量/哈希表大小
load_factor = ht[0].used / ht[0].size
当哈希表的操作不断进行,需要把哈希表的负载因子保持在一个合理范围内,需要对哈希表进行扩容或缩容操作,2种操作都通过执行再散列操作来执行(rehash):
a.为字典的ht[1]分配空间,如果是扩容操作,ht[1]的空间为ht[0]的节点数量2倍;如果是缩容,ht[1]的空间为ht[0]节点数量的一半。
b.将ht[0]中的所有键值对rehash到ht[1]上面:rehash需要重新计算键的哈希值和索引值,然后放在ht[1]的指定位置上。
c.当ht[0]所有键值对都迁移到ht[1]上之后,释放ht[0],就是将ht[0]表置为空表,再将ht[1]置为ht[0],并将ht[1]新建一个大小为0的空哈希表。
4.渐进式rehash
上面讲到rehash过程中,需要将ht[0]上的键值对迁移到ht[1]上,但这个过程并不是一次性操作完成的。如果需要一次性完成,就必须对当前哈希表进行锁表操作,锁表期间会导致服务的不可用,所以rehash操作需要分多次、渐进式的完成。
a.为ht[1]分配空间,字典同时持有ht[0]和ht[1]两个哈希表
b.将rehashidx值置为0,表示rehash工作开始。
c.rehash期间,所有对字典执行的读写操作,都会在ht[0]和ht[1]两个表上操作,读操作如果在ht[0]上找到,会把结果rehash到ht[1]上,如果未找到会到ht[1]上去找,保存操作只会存在ht[1]上,当rehash工作完成之后,rehashidx++;
d.随着字典操作的不断执行,最终ht[0]上所有节点会全部rehash到ht[1]上,这时将rehashidx值置为-1,表示rehash完成。
根据key计算hash值
hash = dict -> type -> hashFunction(key);
根据sizemask属性和哈希值,计算出索引,ht[x]可以是ht[0]或ht[1]
index = hash & dict -> ht[x].sizemask;
Redis使用MurmurHash2算法计算键的哈希值,优点在于即使输入的键是有规律的,算法仍能给出一个很好的随机分布性。
2.解决Hash冲突
当2个或多个不同对象的Hash值相同时,会被分配到哈希表的同一个索引上,此时就称之为哈希冲突。
Redis采用链地址法解决键冲突,每个哈希节点都有一个next指针,由此指针构成一个单向链表,新添加的元素在链表表头。
3.rehash
负载因子 = 哈希表节点数量/哈希表大小
load_factor = ht[0].used / ht[0].size
当哈希表的操作不断进行,需要把哈希表的负载因子保持在一个合理范围内,需要对哈希表进行扩容或缩容操作,2种操作都通过执行再散列操作来执行(rehash):
a.为字典的ht[1]分配空间,如果是扩容操作,ht[1]的空间为ht[0]的节点数量2倍;如果是缩容,ht[1]的空间为ht[0]节点数量的一半。
b.将ht[0]中的所有键值对rehash到ht[1]上面:rehash需要重新计算键的哈希值和索引值,然后放在ht[1]的指定位置上。
c.当ht[0]所有键值对都迁移到ht[1]上之后,释放ht[0],就是将ht[0]表置为空表,再将ht[1]置为ht[0],并将ht[1]新建一个大小为0的空哈希表。
4.渐进式rehash
上面讲到rehash过程中,需要将ht[0]上的键值对迁移到ht[1]上,但这个过程并不是一次性操作完成的。如果需要一次性完成,就必须对当前哈希表进行锁表操作,锁表期间会导致服务的不可用,所以rehash操作需要分多次、渐进式的完成。
a.为ht[1]分配空间,字典同时持有ht[0]和ht[1]两个哈希表
b.将rehashidx值置为0,表示rehash工作开始。
c.rehash期间,所有对字典执行的读写操作,都会在ht[0]和ht[1]两个表上操作,读操作如果在ht[0]上找到,会把结果rehash到ht[1]上,如果未找到会到ht[1]上去找,保存操作只会存在ht[1]上,当rehash工作完成之后,rehashidx++;
d.随着字典操作的不断执行,最终ht[0]上所有节点会全部rehash到ht[1]上,这时将rehashidx值置为-1,表示rehash完成。
相关文章推荐
- Redis命令学习-Transaction(事务)
- redis 工具类
- Yii2 使用十八 使用redis
- Redis命令学习-Pub/Sub(发布/订阅)
- 用Redis实现分布式锁
- Redis 笔记与总结5 Redis 常用命令之 键值命令 和 服务器命令 && 高级应用之 安全性 和 主从复制
- 超强、超详细Redis数据库入门教程
- Redis安装
- redis 管道
- centos6.5 负载均衡(nginx) session共享(redis)
- redis事务详解
- spring+redis整合入门
- PHP使用redis
- Redis 事务
- Redis有序集内部实现原理分析(二)
- 使用twemproxy部署redis集群
- redis的一点用法
- redis cluster 的手工配置
- redis info参数详解
- Redis事务操作