背景
举例说明:
Redis实例:cs1,cs2,cs3
需存储的数据:10000条商品数据
数据与Redis实例的映射方法: hash(商品数据Key) % (Redis实例的个数)
这样,我们就可以将10000条数据利用hash并取模的形式存储到对应的Redis实例中。
这样会出现一个问题,Redis实例的个数可能是变化的,当增加或减少实例时,映射就会改变,若数据量大,将会出现大批量redis请求找不到的情况,会造成缓存击穿甚至缓存雪崩。Hash一致性算法能在一定程度上解决这个问题。
Hash一致性算法介绍
一致性哈希算法通过一个叫作一致性哈希环的数据结构实现。这个环的起点是 0,终点是 2^32 - 1,并且起点与终点连接,故这个环的整数分布范围是 [0, 2^32-1],如下图所示:
若新增一个Redis实例cs4,hsh取模后得到t4,如图所示,则有一部分商品信息将会变化所存储的Redis实例,如k3->t1将会变成k3->t4。虽然会有一部分缓存将失效,但大部分缓存仍旧有效。
一致性hash问题及解决方法
偏斜情况
上图中的Redis实例经过一致性hash算法后得到的值较均匀地分布在hash环上,实际可能并不会出现那么理想的情况,可能会出现Redis实例相邻分布,这样就增加了缓存未击中的几率。
解决办法
针对这个问题,我们可以通过引入虚拟节点来解决负载不均衡的问题。即将每台物理实例虚拟为一组虚拟实例,将虚拟实例放置到哈希环上,如果要确定对象的实例,需先确定对象的虚拟实例,再由虚拟实例确定物理实例。这样就减小了缓存未击中的几率。
缓存读写请求->虚拟实例 ->真实实例->读写