当前位置: 首页 > news >正文

一篇文章带你看懂一致性hash

一致性 Hash 是什么?为什么它是分布式系统中的核心算法

很多程序员第一次接触“一致性 Hash”,都会有一种感觉:

这个名字听起来很高级。

但真正去看资料时,却发现各种概念扑面而来:

  • Hash Ring(哈希环)
  • 虚拟节点
  • 顺时针查找
  • 数据迁移
  • 分布式缓存

最后越看越晕。

我第一次学习一致性 Hash 的时候,也是这种感觉。

直到后来真正做了分布式系统、Redis 集群、分库分表之后,才真正理解:

一致性 Hash 本质上其实是在解决一个非常现实的问题。

也就是:

当服务器数量变化时,如何尽量减少数据迁移。

今天这篇文章,我会尽量用“小白也能看懂”的方式,把一致性 Hash 讲清楚。

包括:

  • 为什么会有一致性 Hash
  • 普通 Hash 的问题是什么
  • 一致性 Hash 如何解决问题
  • 什么是 Hash 环
  • 什么是虚拟节点
  • Redis 为什么后来不用一致性 Hash
  • 工程里真正的使用场景

在进入主题之前,可以先直观的看下一致性hash的原理视频:

5月18日

更多精彩的算法动画,可以访问:算法动图

一、从一个最简单的问题开始

假设现在有 3 台服务器:

ServerA ServerB ServerC

现在我们需要存储用户数据:

user_1 user_2 user_3 ...

那么问题来了:

user_1 应该放到哪台服务器?


最简单的方法是什么?

很多人第一反应就是:

hash(userId) % 服务器数量

例如:

hash(user_1) % 3 = 0 -> ServerA hash(user_2) % 3 = 1 -> ServerB hash(user_3) % 3 = 2 -> ServerC

这就是最经典的:

普通 Hash 分片

它的优点非常明显:

  • 简单
  • 数据比较均匀

很多系统最开始都是这么做的。


二、普通 Hash 最大的问题

问题出现在:

扩容

假设原来:

3 台服务器

后来业务量越来越大。

你发现:

ServerA 快扛不住了。

于是决定:

新增一台机器

变成:

4 台服务器

那么原来的计算规则:

hash(key) % 3

就会变成:

hash(key) % 4

这时候会发生什么?


举个例子。

原来:

hash(user_1) % 3 = 1

可能在:

ServerB

现在:

hash(user_1) % 4 = 2

突然变成:

ServerC

也就是说:

几乎所有数据的位置都变了

这就是普通 Hash 最大的问题。


三、为什么这是灾难?

很多小白第一次看到这里,会觉得:

“位置变了就变了呗,有什么问题?”

实际上问题非常严重。

因为:

数据需要迁移

原来在:

ServerB

现在应该去:

ServerC

那你就得:

  • 把数据重新搬迁
  • 重新同步
  • 重新缓存

如果系统数据量非常大:

几百 GB 几 TB 甚至 PB

那么扩容一次,系统可能直接崩掉。


尤其是:

分布式缓存

比如:

  • Redis
  • Memcached

如果大量 Key 失效:

会出现:

缓存雪崩

数据库压力瞬间暴增。


于是大家开始思考:

有没有一种算法,可以在扩容时,尽量少迁移数据?

这就是:

一致性 Hash 出现的背景


四、一致性 Hash 的核心思想

一致性 Hash 最核心的思想只有一句话:

不再对机器数量取模。

而是:

把整个 Hash 空间组织成一个环。


五、什么是 Hash 环?

假设 Hash 的范围是:

0 ~ 2^32-1

正常情况下它是一条线:

0 ------------------> 2^32-1

一致性 Hash 会把它首尾连接起来:

0 -----------> 2^32-1 ^ | |_______________|

于是:

它变成了一个圆环

这就是:

Hash Ring(哈希环)


六、服务器如何放到环上?

现在我们不再用:

% 服务器数量

而是:

对服务器本身做 Hash

例如:

hash(ServerA) = 100 hash(ServerB) = 500 hash(ServerC) = 800

于是:

ServerA -> 环上的 100 ServerB -> 环上的 500 ServerC -> 环上的 800

整个 Hash 环变成:

0 ----100(A)----500(B)----800(C)----0

七、数据如何找到服务器?

现在:

假设:

hash(user_1) = 320

那么它属于谁?

一致性 Hash 的规则是:

顺时针找到第一个服务器

例如:

320 -> 顺时针找到 500(B)

于是:

user_1 -> ServerB

再比如:

hash(user_2) = 750

顺时针找到:

800(C)

于是:

user_2 -> ServerC

八、一致性 Hash 为什么能减少数据迁移?

重点来了。

假设现在新增一台服务器:

ServerD

Hash 后:

hash(ServerD) = 650

那么环会变成:

0 ----100(A)----500(B)----650(D)----800(C)----0

注意:

只有:

500 ~ 650

这部分数据会受到影响。

也就是说:

只有局部数据需要迁移

其他数据完全不动。

这就是一致性 Hash 最核心的价值。


九、普通 Hash 和一致性 Hash 的区别

普通 Hash:

机器数量变化 ↓ 全部重新计算 ↓ 大量数据迁移

一致性 Hash:

机器变化 ↓ 只影响相邻区间 ↓ 局部数据迁移

这就是为什么它叫:

一致性 Hash

因为它在节点变化时,整体映射关系仍然相对“稳定”。


十、但一致性 Hash 还有一个问题

看到这里很多人会觉得:

“这算法已经很完美了。”

但实际上:

它还有一个非常严重的问题。

数据倾斜


举个例子。

假设:

ServerA -> 100 ServerB -> 110 ServerC -> 900

环:

100(A)---110(B)--------------------900(C)

那么:

110 ~ 900

这一大段数据:

全部归 ServerC。

于是:

  • ServerC 压力巨大
  • A/B 很闲
  • 数据严重不均衡

十一、虚拟节点是怎么解决问题的?

这是很多人第一次学一致性 Hash 时最懵的地方。

其实虚拟节点非常简单。


以前:

一台服务器:

ServerA

只映射一次。

现在:

一台服务器映射很多次

例如:

ServerA#1 ServerA#2 ServerA#3 ServerA#4

它们本质上都代表:

ServerA

只是:

在 Hash 环上有多个位置

例如:

A#1 -> 100 A#2 -> 400 A#3 -> 700 A#4 -> 950

于是:

ServerA 就不再只负责一个大区间。

而是负责:

多个小区间

最终:

数据会更加均匀


十二、为什么虚拟节点效果这么好?

因为:

随机越多,越均匀

如果:

每台机器只有 1 个节点。

那么:

可能运气不好

导致分布极不均匀。

但如果:

每台机器有:

100 个虚拟节点

那么:

大数定律会让整体趋于平均

这也是为什么:

很多工程系统都会使用:

虚拟节点


十三、Redis 为什么后来不用一致性 Hash?

很多人学完一致性 Hash 后,会有一个疑问:

Redis Cluster 为什么不用一致性 Hash?

实际上:

Redis Cluster 使用的是:

Hash Slot(槽位)


Redis 固定定义:

16384 个槽

例如:

slot = CRC16(key) % 16384

然后:

把 Slot 分配给机器

这样做的好处是:

  • 更容易迁移
  • 更容易统计
  • 更容易运维
  • 更容易做主从复制

所以:

现代很多分布式系统,其实已经不直接使用一致性 Hash 了。

而是:

Slot 思想

但一致性 Hash 的思想依旧非常重要。


十四、一致性 Hash 的真实应用场景

它主要用于:


1、分布式缓存

例如:

  • Redis
  • Memcached

客户端根据一致性 Hash 找缓存节点。


2、分库分表

例如:

128 个库 每库 32 张表

很多系统会用一致性 Hash 做路由。


3、CDN

请求:

图片 视频 静态资源

根据一致性 Hash 找缓存节点。


4、对象存储

例如:

  • Cassandra
  • Ceph

十五、一句话理解一致性 Hash

如果让我只用一句话总结:

普通 Hash 解决“怎么分配数据”

一致性 Hash 解决“如何平滑扩容”


十六、最后

很多人第一次学习分布式系统时,会觉得:

一致性 Hash 很复杂。

但当你真正理解它之后,你会发现:

它本质上是在解决一个非常工程化的问题:

如何让系统在不停机的情况下,动态扩容。

而这,恰恰是现代互联网系统最核心的能力之一。

很多算法的伟大之处,并不在于数学有多复杂。

而在于:

它真正解决了现实世界的问题。

http://www.jsqmd.com/news/842398/

相关文章:

  • Agentica智能体框架:从核心架构到实战部署的完整指南
  • 2026年知名的模组吸干机/组合式吸干机主流厂家对比评测 - 行业平台推荐
  • Sora-FullStack全栈开发框架:构建AI视频生成应用的工程实践
  • LeetCode热题100-验证二叉搜索树
  • NotebookLM如何秒级解析PDF文献并生成标准参考文献?——实测12种期刊格式一键适配
  • 告别nmake.opt!用CMake+VS2022在Win11上编译GDAL库为何是更优解?
  • 照片去背景的方法有哪些?2026年最全工具推荐指南
  • 别被“逻辑“吓退了,入门级数字化认证根本不需要你是学霸
  • 深度解锁NVIDIA显卡:200+隐藏参数实战调校指南
  • 别再手动敲符号了!LaTeX + IEEEtran 论文写作的符号速查与高效排版技巧
  • 3步解锁QQ音乐加密文件:qmcdump解密工具完全指南
  • 深入解读Ra-01SCH LoRa模组的RadioSetTxConfig函数:每个参数如何影响你的通信距离与可靠性
  • Legacy iOS Kit终极指南:如何让你的旧iPhone/iPad重获新生
  • Gerbv免费开源Gerber查看器:从新手到专家的完整PCB设计验证指南
  • Fan Control终极指南:Windows免费风扇控制软件完全教程
  • 使用curl命令直接测试taotoken的openai兼容聊天补全接口
  • 基于MCP协议为Gemini模型构建安全可控的外部工具链
  • WarcraftHelper完整指南:三步解决魔兽争霸3在现代系统的兼容性问题
  • Multi-Agent 回滚机制:基于状态版本的任务撤销与恢复方案
  • 个人知识库AI提示词工程:构建专属智能助手的实践指南
  • PADS VX.2.7实战:手把手教你将立创EDA的封装库“搬”进自家项目(附常见报错解决)
  • 解锁NVIDIA显卡隐藏性能:终极调校指南与实战应用
  • 终极指南:SketchUp STL插件如何轻松实现3D打印文件转换
  • Spring AI + Ollama 深度实战:从 RAG 问答到 Graph Agent 全流程指南
  • 坚果投影进化史:每一次新品背后,都是一次行业痛点的拆解
  • 图解UEFI启动:从CPU到PCIe设备,Host Bridge与Root Bridge如何为你铺路?
  • 深度可分离CNN量化优化:PROM方法解析
  • 快速上手SketchUp STL插件:5分钟实现3D模型到打印的无缝转换
  • 事件相机在可见光通信中的技术突破与应用
  • 不只是CT重建:手把手教你用RTK+ITK+VS2022搭建可扩展的医学影像处理开发环境