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

一致性哈希Consistent Hashing

一、简单哈希

在大规模分布式系统中,数据无法全部存放在单台服务器上,而是被“分布”到多台机器中,这种方式称为水平扩展(Horizontal Scaling)。为了让系统在大规模场景下保持可预测的性能,关键在于要将数据尽可能均匀地分布到所有服务器上。简单哈希的方式如下:

// N 是服务器池中的节点数量
serverIndex = hash(key) % N

这种方法在集群规模固定、且数据分布较均匀时效果很好。但当为了应对新的需求而增加服务器,或因维护、故障而移除服务器时,就会导致大量哈希结果失效(cache miss),从而引发大量对象迁移,带来严重的性能抖动。

二、一致性哈希

2.1 简介

一致性哈希正是为了解决上述问题而提出的一种有效技术,它是一种分布式哈希方案。这种方案的目标很简单:在服务器数量发生变化时,尽量让大部分对象仍然保持映射到原有的服务器上。大致的原理是通过在一个抽象的环(hash ring)上为服务器和对象分配位置,从而实现与服务器数量或对象数量无关的哈希映射。

2.2 原理详解
  1. 地址映射:使用一个哈希函数,将每台服务器(通常以服务器名称或 IP 地址作为输入)映射到哈希环上。
  2. 对象键映射:将对象的键(key)通过同一个哈希函数映射到哈希环上。
  3. 查找:查找对象对应的服务器时,从对象键在环上的位置开始,按顺时针方向查找,直到找到第一个服务器节点为止。
    下面通过一个例子来进行讲解:
    在这里插入图片描述
  • key0 落在服务器 s0
  • key1 落在服务器 s1

当我们在环上新增一个服务器时,比如在 s0 左侧插入新节点 s4,只有 key0 需要从 s0 迁移到 s4,因为 s4 是顺时针方向上距离 key0 最近的服务器。其他键(key1key2key3)不会受影响。
一致性哈希的优势: 能够分散负载,并在服务器增加或移除时尽量减少键(key)的重新映射,从而降低系统的抖动风险。

三、潜在问题

一致性哈希也不是完美的,下面是在应用场景中可能会出现的问题。

  1. 热点问题(Hot Spots)
    热门数据可能会导致“热点”现象,也就是某些服务器接收到远超平均水平的流量(即便是整体的哈希分布较均衡)。

虚拟节点(Virtual Nodes)可以在一定程度上缓解这种问题,但会引入额外的复杂性。每新增一个虚拟节点,就需要在哈希环上分配额外的空间,这是需要权衡的地方。

  1. 节点变动导致的负载不均衡
    虽然一致性哈希能够最小化键的重新映射,但在新增服务器或移除服务器时,部分节点的负载可能会显著增加,且分布不均。在数据完全再平衡或缓存预热完成之前,这种问题会更加明显。

  2. 数据副本与可用性问题
    一致性哈希本身并不处理数据副本。当某个服务器发生故障时,如果缺乏完善的数据副本机制,该服务器上存储的歌曲将无法访问。副本管理以及保证副本间的一致性都会增加系统复杂度。

  3. 有状态连接问题
    某些应用可能涉及有状态连接(比如音乐播放器,需要控制用户的播放进度、正在进行的流会话)。如果用户正在使用的服务器发生故障,简单地通过一致性哈希将请求映射到新服务器,可能无法保证无缝体验。需要额外的机制去传递或重建这些状态。

  4. 地理延迟问题
    基础的一致性哈希机制并不会考虑用户与服务器的地理位置接近度。这样可能会导致用户被路由到距离较远的数据中心,从而增加访问延迟。为了解决这一问题,需要引入地理感知哈希(Geo-aware Hashing),但这会增加实现复杂度。

  5. 节点频繁变动的影响(Churn Impact)
    在服务器频繁加入或移除(高 churn)的场景下,即使一致性哈希比传统哈希更具稳定性,也仍会引发大量数据迁移和短暂的服务性能下降。

  6. 实现复杂度
    一个真正健壮的一致性哈希方案,若要同时支持虚拟节点、副本机制、地理感知等功能,其实现和维护难度会非常高,对系统工程能力提出了更高要求。

四、实际应用场景

  • Apache Cassandra:在数据再平衡过程中,尽量减少数据迁移。
  • 内容分发网络(CDN):将网页内容均匀地分布到边缘服务器。
  • 负载均衡器:将持久连接均匀分布到后端服务器。
http://www.dtcms.com/a/330876.html

相关文章:

  • Rust Web框架Axum学习指南之入门初体验
  • Java面试宝典:JVM性能优化
  • 【代码随想录day 20】 力扣 669. 修剪二叉搜索树
  • MySQL 性能优化实战指南:释放数据库潜能的艺术
  • 【visual studio】visual studio配置环境opencv和onnxruntime
  • 零知开源——基于STM32F4的HC-12无线通信系统及ST7789显示应用
  • 【Linux】库制作与原理
  • mysql卸载了 服务内还显示如何解决
  • CVPR 2025丨时间序列:动态多尺度机制登场,即插即用,预测稳准狠刷新SOTA
  • Vivado GPIO详解
  • 量化因子RSI
  • 中小型泵站物联网智能控制系统解决方案:构建无人值守的自动化泵站体系
  • 基于STM32单片机智能手表GSM短信上报GPS定位温湿度检测记步设计
  • OS设备UDID查看方法
  • Mybatis学习笔记(一)
  • 「iOS」————设计架构
  • 在语音通信业务量下降时候该怎么做
  • PHP现代化全栈开发:微服务架构与云原生实践
  • 基于FPGA的8PSK+卷积编码Viterbi译码通信系统,包含帧同步,信道,误码统计,可设置SNR
  • 一台联想 ThinkCentre M7100z一体机开机黑屏无显示维修记录
  • 优化 SQL 查询:选出每个分组最大值的行并插入 10W 条测试数据
  • 云计算-Docker Compose 实战:从OwnCloud、WordPress、SkyWalking、Redis ,Rabbitmq等服务配置实例轻松搞定
  • 【代码随想录day 20】 力扣 108.将有序数组转换为二叉搜索树
  • 老生常谈之引用计数:《More Effective C++》条款29
  • 炎热的夏天
  • SQL181 第二快/慢用时之差大于试卷时长一半的试卷
  • 掌握MATLAB三维可视化:从基础到实战技巧
  • Redis 从入门到生产:数据结构、持久化、集群、工程实践与避坑(含 Node.js/Python 示例)
  • jenkins在windows配置sshpass
  • 构建Node.js单可执行应用(SEA)的方法