前言
一周前面试某外企被问到什么是一致性哈希,当时脑子一片空白,现在我来讲清一致性哈希的前世今生
分布式缓存
随着业务的扩展,流量的剧增,单体项目逐渐划分为分布式系统,对于经常使用的数据可以使用缓存层减少数据层的压力
将数据缓存到Redis当中去,每次请求会随时发送到一台Redis当中去,但是也会出现问题
- 同一份数据可能在多个Redis数据库,造成数据冗余
- 无法保证相同的请求会发送到相同Redis当中去,可能第一次访问到Redis 1第二次访问到Redis 2
解决方案
- 改变Key存入Redis的方法:使用一定的Hash算法,进行一定关系的映射,h = (key)%3,相当于是计算出一个哈希值来对应的Redis服务器
- 容错性:当系统当中的某一个服务出现问题,不能影响其他服务
- 扩展性:加入新的服务器的时候,整个系统能正确高效运行
- 如果有一台服务器服务器宕机了那么需要将服务器从列表当中移除,并且每一个节点的算法都需要进行改变h = (key)%2
- 同时如果有一台服务器新增的话,也需要重新进行计算,哈希算法也需要改变
系统中如果有服务器变更,会直接影响到hash值,大量的key会进行重定向到其他服务器中,造成缓存命中率降低,而这种情况不是我们想在分布式系统中看到的
一致性哈希算法
一致性哈希算法是一种特殊的哈希算法,一致性哈希算法也使用了取模计算,一致哈希算法是对 2^32 进行取模运算,是一个固定的值
- 整体上一致性可以看作一个圆环,把这个圆想象成由 2^32 个点组成的圆,这个圆环被称为哈希环,如下图:
一致性哈希:
-
第一步:对存储节点进行哈希计算,也就是对存储节点做哈希映射,比如节点的IP地址等等
-
第二步:当对数据进行存储或访问时,对数据进行哈希映射 将数据和存储节点都映射到一个首尾相连的哈希环上
-
对数据进行哈希映射的话怎么找到该节点?
- 数据的哈希顺时针找到第一个存储节点
两大特性
容错性
- 加入当中的Redis 2宕机,那么B的数据就会保存在Redis 3当中,如果一台宕机影响面比较小
扩展性
- 当增加了一台Redis,数据C会分配到Redis4当中去,影响面也会比较小
虚拟节点
前面我们的场景都是Redis分布比较均匀的场景,如果节点较少就会出现不均匀的场景 e.g.
可以看出Redis 1的哈希范围比Redis 2哈希范围更广一些,这就会导致数据存储的不均匀性
- 为了解决这种数据不平衡的问题,一致性哈希算法引入了虚拟节点机制,即对某一个节点做多个映射关系,也就是虚拟节点到真实节点有一层映射关系
- 可以通过节点后面增加编号来实现
- 节点数量多了之后,节点的分布相对就均匀了
- 虚拟节点不仅能够提高节点的均衡性也能提高系统的稳定性,当节点变化时,会有不同的节点分担系统的变化,因此稳定性更高