在分布式缓存集群扩容、缩容场景中,普通取模 Hash 算法存在致命缺陷:节点数量变更时,hash(key) % N 映射关系大面积失效,绝大多数缓存 Key 路由到新节点,引发大规模缓存失效、缓存雪崩。一致性 Hash 正是为解决该痛点诞生——保证集群增减节点时,仅少量缓存 Key 发生迁移。
传统分布式缓存路由方案:nodeIndex = hash(key) % N。当集群节点数量 N 变更时,几乎所有 Key 的取模结果都会改变,引发大规模缓存失效与雪崩。
假设集群拥有 3 台缓存节点 N=3,当扩容至 4 台节点 N=4,几乎所有 Key 的取模结果都会改变。下方为两种方案在节点变更后的缓存失效率对比:
一致性 Hash 将 Hash 值空间设定为 0 ~ 2³²-1,把值域首尾相连形成环形结构。节点和 Key 都映射到环上,Key 顺时针遇到的第一个节点即为归属节点。
对缓存节点 IP/名称进行 Hash 运算,映射到圆环上对应的位置;对缓存 Key 进行 Hash 运算,定位到圆环上的坐标;沿着 Hash 环顺时针查找,遇到的第一个节点即为当前 Key 归属节点。
对比普通取模 Hash:一致性 Hash 扩缩容,只有一小部分缓存数据需要迁移,极大降低缓存失效范围。
在 Node-A 与 Node-B 之间插入 Node-E,原本归属 Node-B 的部分 Key(落在新节点逆时针方向)会被分割给 Node-E。其余节点上的 Key 完全不受影响。
Node-B 宕机下线,原本归属 Node-B 的所有 Key,顺延至顺时针下一个节点(Node-C)。其余节点上的 Key 完全不受影响。
直接将物理节点映射到 Hash 环存在严重问题:节点数量较少时,物理节点在环上分布不均匀,大量缓存 Key 集中落在少数节点,出现数据倾斜,节点负载不均衡。例如 3 台服务器,大量流量集中到其中一台节点,节点资源耗尽,其余节点闲置。
为解决数据倾斜,引入虚拟节点(Virtual Node)。不再直接把物理节点放入 Hash 环,而是为每一台真实物理节点生成数百 / 上千个虚拟副本。
含虚拟节点。使用 TreeMap 的 SortedMap 作为 Hash 环底层结构,tailMap 顺时针查找最近节点,MD5 作为 Hash 函数保证均匀分布。
一致性 Hash 在 Memcached 客户端是经典应用,但 Redis Cluster 走的是另一条路。很多人存在误区,把两者混为一谈。
四类高频踩坑场景,每一类都对应过真实的线上故障。规避成本远低于复盘成本。
一致性 Hash 不是万能分片方案。下方为线上选型时的明确判断标准。
一致性 Hash 是分布式分片领域经典算法,核心价值就是最小化节点变动带来的数据迁移代价。在实际开发中,不能只停留在理论层面,必须理解虚拟节点解决倾斜的原理,同时区分 Memcached 客户端集群与 Redis Cluster 两种不同分片方案,避免技术选型踩坑。
算法的优雅不在于复杂,而在于用最小的代价解决最痛的问题——这正是一致性 Hash 成为分布式缓存基石的原因。