Redis中的一致性哈希
Redis中的一致性哈希是怎么实现的?
一般的哈希算法
一般的哈希算法,对 key 调用hash()算法得到这个 key 对应的hashCode,再对服务器的个数取模得到一个值,这个值就是这个key应该放到的对应的主机上。
例如:有3台redis主机: 0, 1, 2.
hash(key) % 3 = 0;
那么这个key就放在第 0 台主机上
但是这种一般的hash算法存在很大的问题:
当我们增加主机数量后,就会产生很大的问题。
例如:
上面的key, 我们假设对key使用hash()函数得到的hashCode为6.
hash(key) % 3 = 0; 这个key应该存在第0台主机上.
如果在集群中增加了一台主机,那么,再去查找这个key时,
hash(key) % 4 = 2; 应该到第2台主机上去找这个key。但是这个key是存到了第0台主机上的。这种一般的哈希算法会使得大量的缓存查找不到,查找不到的话就会到数据库去查询,这样就会给DB造成很大的压力。
正因为如此,一致性哈希算法就是被提出来解决这个问题的。
一致性哈希算法
一致性哈希是让在增加主机数量的情况下,绝大部分的Redis缓存查找都是有效的,只有极少部分查找会失效。
当我们增加节点时,如下图:
key3被映射到了节点D上,而key3本来被存储到节点A上。但是其他的key都能正确的查找到它对应的存储节点,被影响的只是(C, D)这一小段的key。
而一般的hash算法所有的key都会被影响到。
一致性哈希中海油可能存在 倾斜 的问题,如下图:
当主机映射在hash环上不均匀时,有可能很多key存储到了一台主机上,而其他的主机相对少很多。
解决办法
很显然,当hash环中的主机越多,那么hash环上的key被存储得就越均匀。
可以把每一个物理主机虚拟成多个虚拟主机,多个虚拟主机映射到hash环上。这样,当key存储/查找时先找到它对应的虚拟主机,由虚拟主机再存储到物理主机上。如下图:
读写流程如下:
这样发就可以保证key均匀分布在各个主机节点中了。并且在增加主机节点时,被影响的只有很少的一部分key,就不会出现上面一般哈希算法中存在的问题了。