在电商服务中, 热点商品信息存储在Redis缓存中。数据量小的场景下,使用单个节点存储。随着数据量的增长,一般采用多节点集群模式管理。算法
将请求均匀分配到各个服务器节点。假设有4个Redis服务节点,能够取商品对象hash值,经过算法 hash(object)/(4)均匀映射到每一个服务节点数据库
当Redis服务器从4个扩容到5个,咱们发现只有4个对象能够命中缓存(图中绿色的点),致使其余大量的请求穿透缓存,压力所有到数据库,后果不可预料。缓存
咱们发现hash分布的结果是关键,能够将Redis服务器从4个扩容到8个这样成倍的扩容。已经经过哈希分派到了相应的缓存,原有的映射才不会改变。服务器
成倍的扩容彷佛解决了扩容问题,可是成倍扩容会致使资源的浪费,并且集群的收缩性不是很好。更重要的是,Redis服务器故障移除时,一样致使上述的穿透缓存问题。为了解决缓存服务器数量发生变化致使的问题,咱们引入了一致性哈希算法分布式
一致性哈希算法仍然是取模的算法。一致性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个商品存储在哪一个缓存节点上。spa
一致性哈希算法是否解决了缓存服务器数量发生变化致使的问题?
咱们假设节点Redis-1故障了,商品A的Hash值为2157132,找到在hash环上的位置,而后顺时针查找第一个服务器节点Redis-2.Hash值落在其余区间的对象和服务器的映射关系没有收到影响。设计
咱们新增节点Redis-5(1072132),商品A的Hash值为2157132,找到在hash环上的范围1064231~1072132,而后顺时针查找第一个服务器节点Redis-5. Hash值落在其余区间的对象和服务器的映射关系没有收到影响。3d
当服务器节点发生变动,只有部分缓存失效,不会出现大范围缓存失效的问题。对象
上文讲到节点Redis-1故障时,全部缓存在节点Redis-1的数据都会缓存到节点Redis-2上,这样就会致使一个缓存分布不均衡的问题,大量缓存集中在某几个节点上。
从另外一个角度来讲,是hash环没有被平均的切分致使的散列不均衡。那么咱们多建立几个节点就能解决这个问题。由于实际上物理服务器是固定的,那么咱们建立虚拟节点作分布。
为每一个Redis节点建立3个虚拟节点,虚拟节点自身关联到物理节点。
因为多个节点,整个hash环被分红9个区间,Redis-1 负责映射到区间2,4,6的对象,总体来看每一个Redis服务器承担的区间压力更加均匀。
一致性哈希算法设计是为了解决分布式Cache中提出的,设计目标是为了解决在分布式服务节点变动,使用简单哈希算法带来的问题。在实际使用中,如何保证分布式服务的稳定性,是服务设计首先要考虑的问题。