一、一致性哈希的核心原理

        哈希取模最大的痛点是:当分片数量(例如数据库节点数)发生变化时,几乎所有数据的哈希结果都会改变,导致大规模的数据迁移。一致性哈希就是为了解决这个“伸缩性差”的问题而诞生的。

核心思想:数据和节点共舞的“虚拟圆环”

        一致性哈希不再简单粗暴地用数据哈希值对节点数量取模。它的核心在于引入了一个 “哈希环”(Hash Ring 或 Hash Circle)的概念。你可以把这个哈希环想象成一个巨大的虚拟圆盘,它的周长覆盖了所有可能的哈希值范围(比如从0到 ^{2^{32}}-1,或者 ^{2^{64}}−1,取决于哈希算法的输出范围)。

在这个哈希环上,有两类重要的参与者:

  1. 存储节点(服务器/数据库):

    • 我们不再直接用服务器数量做模数。而是将每一个真实的存储节点(比如你的 db_0db_1db_2 这些数据库服务器),通过一个哈希函数计算出一个哈希值。

    • 这些哈希值就相当于服务器在圆环上的“座标点”。每个节点都会根据自己的哈希值,被放置到哈希环上的一个特定位置。

  2. 数据记录:

    • 同样地,每一条待存储的数据记录(比如一个用户的信息、一个订单的详情),我们会选择它的某个字段作为分片键(比如 user_idorder_id)。

    • 然后,我们用同样的哈希函数计算这个分片键的哈希值,把数据也映射到哈希环上的一个位置。这个哈希值就像是数据的“身份证号码”,它也对应着圆环上的一个“座标点”。

        哈希环示意图: 

                       

智能罗盘:数据如何找到它的“归宿”?

        当一条数据(或一个查询请求)要寻找它的存储位置时,一致性哈希的“智能罗盘”就会启动:

  • 数据路由法则:从数据在哈希环上的存储数据位置开始,沿着圆环顺时针方向查找,遇到的第一个存储节点,就是这条数据存储的节点位置!

比如,在该哈希环上: 

  • data1 存储在 nodeA

    • data1 位于 0nodeA 之间。从 data1 顺时针查找,遇到的第一个存储节点是 nodeA

  • data2 存储在 nodeB

    • data2 位于 nodeA 和 nodeB 之间。从 data2 顺时针查找,遇到的第一个存储节点是 nodeB

  • data3 存储在 nodeC

    • data3 位于 nodeB 和 nodeC 之间。从 data3 顺时针查找,遇到的第一个存储节点是 nodeC

  • data4 存储在 nodeA

    • data4 位于 nodeC0 之间(或者说 nodeC2^32-1  之间,因为环是闭合的)。从 data4 顺时针查找,遇到的第一个存储节点是 nodeA


二、一致性哈希执行案例

我们来设计一个简单且易于理解的一致性哈希执行案例。我们将聚焦在一个非常常见的场景:一个简单的分布式缓存系统

场景设定:

        假设你正在开发一个热门的社交应用,其中有很多用户头像图片需要缓存。为了提高访问速度和系统承载能力,你决定使用多个缓存服务器来存储这些图片。当用户请求某个头像时,你需要知道这张图片存在哪个缓存服务器上。

  • 缓存内容:用户头像图片。

  • 唯一标识user_id (用户ID),我们将用它作为分片键。

  • 缓存服务器:初始有 3 台服务器,命名为 CacheA, CacheB, CacheC

我们将使用一致性哈希来决定每张图片存储在哪台缓存服务器上。

步骤一:服务器“入座”哈希环

在系统启动时,我们的缓存服务器需要先在哈希环上找到自己的“座位”。

  • 我们会用哈希函数计算每台服务器名称的哈希值:

    • Hash("CacheA") rightarrow 假设得到 100

    • Hash("CacheB") rightarrow 假设得到 1500

    • Hash("CacheC") rightarrow 假设得到 3000

我们在这假设该哈希函数计算的哈希值在0-3599之间

(注:为了简化,实际哈希值范围很大,这里用小数字示意相对位置) 

我们将这些哈希值标注在哈希环上:

                           

步骤二:用户头像图片“找主人”

        现在,当用户请求或上传一张头像(user_id)时,系统需要知道它应该存在哪台缓存服务器上。

我们以两个用户为例:

  1. 用户ID: 1001 的头像

    • 我们用同样的哈希函数计算 user_id = 1001 的哈希值:

      Hash("1001") rightarrow 假设得到 500

    • 500 标注在哈希环上。

    • 查找规则:从 500 这个点开始,沿着哈希环顺时针方向查找,遇到的第一个缓存服务器是谁,它就归谁管。

    • 根据图示,从 500 顺时针,第一个遇到的服务器是 CacheB (1500)。

    • 结论用户1001的头像 存储到 CacheB

  2. 用户ID: 2002 的头像

    • Hash("2002") rightarrow 假设得到 3200

    • 3200 标注在哈希环上(这里同上,我就不在画了)。

    • 查找规则:从 3200 顺时针查找,由于环是闭合的,它会绕过 3599 重新从 0 开始,遇到的第一个服务器是 CacheA (100)。

    • 结论用户2002的头像 存储到 CacheA

步骤三:服务器扩容,一致性哈希显神通

       假设现在,你的社交应用用户量暴增,CacheA, CacheB, CacheC 三台服务器已经不够用了!你需要新增一台缓存服务器:CacheD

  • 哈希取模的痛点:如果是传统哈希取模 (Hash(user_id) % N),N从3变成4,那几乎所有用户头像的位置都会重新计算,你需要把大量头像数据从旧服务器搬到新位置,系统可能要停机维护,非常麻烦!

  • 一致性哈希的优势

    1. CacheD “入座”哈希环

      • 我们计算 Hash("CacheD") rightarrow 假设得到 2000

      • CacheD (2000) 放置在哈希环上。它会落在 CacheB (1500) 和 CacheC (3000) 之间。

    2. 数据迁移分析

      • 观察哈希环,CacheD 的加入,只会影响到它逆时针方向的那个服务器(CacheB)所负责的部分数据

      • 原来从 CacheB (1500) 顺时针到 CacheC (3000) 的这部分区间,现在被 CacheD (2000) 分割了。

      • 只有那些哈希值在 15002000 之间的用户头像,需要从 CacheB 迁移到 CacheD

      • CacheA 负责的头像数据、以及 CacheB 负责的哈希值小于 1500 的头像数据,位置完全不变!

                      

        这一特性是衡量分布式系统可伸缩性的关键优势。相比于传统哈希取模在节点变化时需要进行全局数据重分布,一致性哈希实现了渐进式、低影响的扩容/缩容操作,极大地降低了系统维护成本和业务中断风险。


三、总结:

         一致性哈希算法通过将数据键与存储节点共同映射至一个环形哈希空间,并基于“顺时针最近匹配”原则进行数据路由,从而巧妙地解决了分布式系统在扩容或缩容场景下,传统哈希取模算法导致的大规模数据迁移问题。这一机制显著提升了系统的弹性伸缩能力和可用性。在构建高性能、高可扩展性的分布式缓存或分布式存储系统时,一致性哈希提供了一种高效且稳定的数据分布与管理策略。

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/88320.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/88320.shtml
英文地址,请注明出处:http://en.pswp.cn/pingmian/88320.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

前端学习 vben 之 axios interceptors

前端学习 vben 之 axios interceptors interceptor 拦截器,是一种软件设计模式,核心思想就是在程序执行的特定阶段(如请求发送前,响应返回后,方法调用前后等)自动插入自定义逻辑。实现对核心流程的“拦截”…

【java面试day4】redis缓存-数据持久化

文章目录问题💬 Question 1相关知识问题 💬 Question 1 Q:redis作为缓存,数据的持久化是怎么做的? A:有两种机制,一种是RDB,RDB会在指定的时间间隔内将内存中的数据生成快照,保存…

Vue3中element plus默认获取最近一周和上个月的时间区间并在后端分开传值

<el-form-item label"结算时间&#xff1a;" prop"datetimerangevalue"><el-date-pickerv-model"datetimerangevalue"value-format"YYYY-MM-DD HH:mm:ss"type"datetimerange"range-separator"至"start-p…

SQLAlchemy数据库连接密码特殊字符处理完全指南

引言 在使用SQLAlchemy连接数据库时&#xff0c;我们通常使用URL格式指定连接信息&#xff0c;如mysqlpymysql://user:passwordhost:port/database。然而&#xff0c;当密码中包含特殊字符&#xff08;如、#、$、!等&#xff09;时&#xff0c;会导致URL解析错误&#xff0c;进…

1.4 ARM安全参考架构(PSA Certified)

目录1.4.1 PSA Certified概述1.4.2 PSA认证级别详解1.4.3 PSA与TF-A的关系1.4.4 PSA安全模型实现信任根(RoT)架构关键安全服务&#xff1a;1.4.5 认证流程实践1.4.6 典型应用案例参考资料1.4.1 PSA Certified概述 ARM Platform Security Architecture (PSA) Certified 是一套完…

企业网络安全的“金字塔”策略:构建全方位防护体系的核心思路

在数字化转型的浪潮中&#xff0c;企业的网络安全已从单一的防护措施&#xff0c;发展成为多层次、全方位的安全体系。如何精准应对日益复杂的网络威胁&#xff0c;成为众多企业关注的焦点。本文将分享企业构建高效安全防护“金字塔”的核心思路。一、从“排查隐患”到“主动防…

爬虫-request模块使用

1.使用和安装2.代码测试打印返回的内容&#xff0c;默认是请求体中的标识.text 是打印源代码设置一下编码

HTML + CSS + JavaScript

目录 1 HTML HTML 文件基本结构 HTML 开发工具 HTML 常见标签 标题标签&#xff1a;h1 - h6 段落标签&#xff1a;p 换行标签&#xff1a;br 图片标签&#xff1a;img 超链接标签&#xff1a;a 表格标签 表单标签 form 标签 input 标签 select 标签 textarea 标…

Java 与 MySQL 性能优化:MySQL连接池参数优化与性能提升

文章目录引言一、连接池的基本概念与作用二、关键连接参数详解2.1 max_connections2.2 wait_timeout2.3 interactive_timeout2.4 connect_timeout2.5 thread_cache_size三、连接池参数不合理导致的性能问题3.1 连接耗尽3.2 响应变慢3.3 连接失效3.4 资源浪费四、连接池参数优化…

浪潮CD1000-移动云电脑-RK3528芯片-2+32G-开启ADB ROOT破解教程

浪潮CD1000-移动云电脑-RK3528芯片-232G-安卓9-开启ADB ROOT破解教程破解教程&#xff1a;1.先下载好开心电视助手&#xff08;下载地址及其他版本&#xff1a;【工具大全】-【开心电视助手3.8&#xff0f;4.0&#xff0f;4.6&#xff0f;6.0&#xff0f;6.2&#xff0f;6.3&am…

【网络编程】简易的 p2p 模型,实现两台虚拟机之间的简单点对点通信,并以小见大观察 TCP 协议的具体运行

文章目录基本概念业务拆解代码实现准备工作实现被动的功能——多线程指针函数实现主动的功能——用户选择界面主函数代码执行效果意外收获总结推荐一个零声教育学习教程&#xff0c;个人觉得老师讲得不错&#xff0c;分享给大家&#xff1a;[Linux&#xff0c;Nginx&#xff0c…

react状态管理库 - zustand

什么是zustand&#xff1f; zustand 是一个轻量级、快速且可扩展的 React 状态管理库&#xff0c;旨在提供一种简单直接的方式来管理应用状态&#xff0c;而无需其他解决方案通常伴随的繁琐代码。根据官方 Zustand 文档&#xff0c;Zustand 是“一个使用简化 flux 原理的小型、…

粗排样本架构升级:融合LTR特征提升模型性能的技术实践

粗排样本架构升级&#xff1a;融合LTR特征提升模型性能的技术实践 ——基于PySpark的样本构建与特征工程深度解析 一、粗排系统的定位与技术演进 在推荐系统级联架构中&#xff0c;​粗排&#xff08;Rough Ranking&#xff09;​​ 承担着关键过渡角色&#xff1a;从召回层获…

CCF-GESP 等级考试 2025年6月认证C++四级真题解析

1 单选题&#xff08;每题 2 分&#xff0c;共 30 分&#xff09;第1题 在C中&#xff0c;声明一个指向整型变量的指针的正确语法是&#xff08; &#xff09;。A. int* ptr; B. *int ptr; C. int ptr*; D. ptr …

PlantUML 在 IDEA 中文版中的安装与使用指南

目录 摘要 一、安装 PlantUML 插件 二、配置 PlantUML 运行环境 三、创建 PlantUML 文件 四、编写 PlantUML 代码 五、生成并查看图表 六、自动生成类图&#xff08;重点新增&#xff09; 6.1 从 Java 类生成类图 6.2 类图语法详解 6.3 类图高级技巧 七、常见问题及…

创客匠人:创始人 IP 打造中 “放下身段” 的深层逻辑

在 IP 经济火热的当下&#xff0c;无数创始人投身 IP 打造&#xff0c;却鲜少有人意识到&#xff1a;真正能实现 IP 变现的核心&#xff0c;并非专业知识的堆砌&#xff0c;而是与用户建立 “可交往” 的连接。创客匠人通过多年服务 IP 的实践发现&#xff0c;那些穿越周期的创…

C语言<数据结构-链表>

链表是一种常见且重要的数据结构&#xff0c;在 C 语言中&#xff0c;它通过指针将一系列的节点连接起来&#xff0c;每个节点可以存储不同类型的数据。相比数组&#xff0c;链表在插入和删除元素时不需要移动大量数据&#xff0c;具有更好的灵活性&#xff0c;尤其适合处理动态…

基于Matlab多特征融合的可视化指纹识别系统

针对中小规模&#xff08;百级&#xff09;指纹模板库中常见的脊线断裂、噪声干扰以及结果缺乏可解释性等难点&#xff0c;本文提出并实现了一种基于多特征融合的可视化指纹识别系统。系统整体采用模块化设计&#xff1a;在预处理阶段&#xff0c;先通过改进的灰度归一化与局部…

50天50个小项目 (Vue3 + Tailwindcss V4) ✨ | DoubleVerticalSlider(双垂直滑块)

&#x1f4c5; 我们继续 50 个小项目挑战&#xff01;—— DoubleVerticalSlider组件 仓库地址&#xff1a;https://github.com/SunACong/50-vue-projects 项目预览地址&#xff1a;https://50-vue-projects.vercel.app/ 使用 Vue 3 的 Composition API&#xff08;<scrip…

mysql join语句、全表扫描 执行优化与访问冷数据对内存命中率的影响

文章目录join执行逻辑Index Nested_Loop Join&#xff08;NLJ&#xff09;MMR(Mutli-Range Read) 优化BKA(Batched Key Access)算法Simple Nested_Loop JoinBlock Nested-Loop Join&#xff08;BLJ&#xff09;join buffer 一次放不下 驱动表join buffer优化的影响&#xff1a;…