「拒绝等通知」我还会一致性哈希算法

一致性哈希算法

1. 基本场景

在电商服务中, 热点商品信息存储在Redis缓存中。数据量小的场景下,使用单个节点存储。随着数据量的增加,通常采用多节点集群模式管理。

2. 哈希取模

将请求均匀分配到各个服务器节点。假设有4个Redis服务节点,可以取商品对象hash值,通过算法 hash(object)/(4)均匀映射到每个服务节点

3. 哈希取模的缺陷

扩容导致的灾难

当Redis服务器从4个扩容到5个,我们发现只有4个对象可以命中缓存(图中绿色的点),导致其他大量的请求穿透缓存,压力全部到数据库,后果不可预料。

解决方案:成倍扩容

我们发现hash分布的结果是关键,可以将Redis服务器从4个扩容到8个这样成倍的扩容。已经通过哈希分派到了相应的缓存,原有的映射才不会改变。

成倍的扩容似乎解决了扩容问题,但是成倍扩容会导致资源的浪费,而且集群的收缩性不是很好。更重要的是,Redis服务器故障移除时,同样导致上述的穿透缓存问题。为了解决缓存服务器数量发生变化导致的问题,我们引入了一致性哈希算法

4. 一致性哈希算法

一致性哈希算法仍然是取模的算法。一致性Hash算法将整个哈希值空间组织成一个虚拟的圆环,通常哈希函数值空间为0-2^32-1.

假设我们有4台服务器,Redis-1(10.0.1.156),Redis-1(10.1.2.145),Redis-1(10.2.3.112),Redis-1(10.6.4.231)
我们使用一个简单的hash函数:hash(Redis-1) = 1001156,将服务器映射到哈希环。

可以看到,4个节点将哈希环分为4个部分. 假设有个商品A的Hash值为2157132,找到在hash环上的范围1064231~1001156,然后顺时针查找第一个服务器节点Redis-1,就是我们的缓存节点。以此类推图中4个商品存储在哪个缓存节点上。

5. 一致性哈希算法的优点

一致性哈希算法是否解决了缓存服务器数量发生变化导致的问题?
我们假设节点Redis-1故障了,商品A的Hash值为2157132,找到在hash环上的位置,然后顺时针查找第一个服务器节点Redis-2.Hash值落在其他区间的对象和服务器的映射关系没有收到影响。

我们新增节点Redis-5(1072132),商品A的Hash值为2157132,找到在hash环上的范围1064231~1072132,然后顺时针查找第一个服务器节点Redis-5. Hash值落在其他区间的对象和服务器的映射关系没有收到影响。

当服务器节点发生变更,只有部分缓存失效,不会出现大范围缓存失效的问题。

6. Hash倾斜

上文讲到节点Redis-1故障时,所有缓存在节点Redis-1的数据都会缓存到节点Redis-2上,这样就会导致一个缓存分布不均衡的问题,大量缓存集中在某几个节点上。

从另一个角度来说,是hash环没有被平均的切分导致的散列不均衡。那么我们多创建几个节点就能解决这个问题。因为实际上物理服务器是固定的,那么我们创建虚拟节点做分布。

为每个Redis节点创建3个虚拟节点,虚拟节点自身关联到物理节点。


由于多个节点,整个hash环被分成9个区间,Redis-1 负责映射到区间2,4,6的对象,整体来看每个Redis服务器承担的区间压力更加均匀。

7. 总结

一致性哈希算法设计是为了解决分布式Cache中提出的,设计目标是为了解决在分布式服务节点变更,使用简单哈希算法带来的问题。在实际使用中,如何保证分布式服务的稳定性,是服务设计首先要考虑的问题。

你可能感兴趣的:(一致性哈希算法,redis)