【负载均衡——一致性哈希算法】

1.一致性哈希是什么

一致性哈希算法就很好地解决了分布式系统在扩容或者缩容时,发生过多的数据迁移的问题。

一致哈希算法也用了取模运算,但与哈希算法不同的是,哈希算法是对节点的数量进行取模运算,而一致哈希算法是对 2^32 进行取模运算,是一个固定的值。

一致性哈希要进行两步哈希:
第一步:对存储节点进行哈希计算,也就是对存储节点做哈希映射,比如根据节点的 IP 地址进行哈希;
第二步:当对数据进行存储或访问时,对数据进行哈希映射;

一致性哈希是指将【存储节点】和【数据】都映射到一个首尾相连的哈希环上
在这里插入图片描述

  • 首先,对key进行哈希计算,确定此key在换上的位置
  • 然后,从这个位置沿着顺时针方向走,遇到的第一节点就上存储key的节点

2. 使用的场景是什么

在负载均衡问题中,不同的负载均衡算法,对应的就是不同的分配策略,适应的业务场景也不同。

  • 最简单的方式,引入一个中间的负载均衡层,让它将外界的请求「轮流」的转发给内部的集群。
  • 考虑到每个节点的硬件配置有所区别,我们可以引入权重值,将硬件配置更好的节点的权重值设高,然后根据各个节点的权重值,按照一定比重分配在不同的节点上,让硬件配置更好的节点承担更多的请求,这种算法叫做加权轮询。
    在这里插入图片描述

但是,加权轮询算法是无法应对「分布式系统(数据分片的系统)」的,因为分布式系统中,每个节点存储的数据是不同的。

比如一个分布式 KV(key-valu) 缓存系统,某个 key 应该到哪个或者哪些节点上获得,应该是确定的,不是说任意访问一个节点都可以得到缓存结果的。

3. 使用哈希算法的问题

哈希算法能够对同一个关键字进行哈希计算,每次计算都是相同的值,这样就可以将某个key确定到一个节点了,可以满足分布式系统的负载均衡需求。

存在的致命问题:如果节点数量发生了变化,也就是在对系统做扩容或者缩容时,必须迁移改变了映射关系的数据,否则会出现查询不到数据的问题。

要解决这个问题的办法,就需要我们进行迁移数据,比如节点的数量从 3 变化为 4 时,要基于新的计算公式 hash(key) % 4 ,重新对数据和节点做映射。

假设总数据条数为 M,哈希算法在面对节点数量变化时,最坏情况下所有数据都需要迁移,所以它的数据迁移规模是 O(M),这样数据的迁移成本太高了。

4.一致性哈希算法进阶

4.1 一致性哈希算法存在的问题

一致性哈希算法并不保证节点能够在哈希环上分布均匀,这样就会带来一个问题,会有大量的请求集中在一个节点上。
在这里插入图片描述
上图中如果节点 A 被移除了,当节点 A 宕机后,根据一致性哈希算法的规则,其上数据应该全部迁移到相邻的节点 B 上,这样,节点 B 的数据量、访问量都会迅速增加很多倍,一旦新增的压力超过了节点 B 的处理能力上限,就会导致节点 B 崩溃,进而形成雪崩式的连锁反应。

所以,一致性哈希算法虽然减少了数据迁移量,但是存在节点分布不均匀的问题。

4.2 通过虚拟节点提高均衡度

要想解决节点能在哈希环上分配不均匀的问题,就是要有大量的节点,节点数越多,哈希环上的节点分布的就越均匀。

但问题是,实际中我们没有那么多节点。所以这个时候我们就加入虚拟节点,也就是对一个真实节点做多个副本。

具体做法是,不再将真实节点映射到哈希环上,而是将虚拟节点映射到哈希环上,并将虚拟节点映射到实际节点,所以这里有「两层」映射关系。

比如对每个节点分别设置 3 个虚拟节点:

对节点 A 加上编号来作为虚拟节点:A-01、A-02、A-03
对节点 B 加上编号来作为虚拟节点:B-01、B-02、B-03
对节点 C 加上编号来作为虚拟节点:C-01、C-02、C-03
引入虚拟节点后,原本哈希环上只有 3 个节点的情况,就会变成有 9 个虚拟节点映射到哈希环上,哈希环上的节点数量多了 3 倍。

在这里插入图片描述
节点数量多了后,节点在哈希环上的分布就相对均匀了。这时候,如果有访问请求寻址到「A-01」这个虚拟节点,接着再通过「A-01」虚拟节点找到真实节点 A,这样请求就能访问到真实节点 A 了。

总结

  • 一个真实节点对应N个虚拟节点
  • 一个虚拟节点对应N个key

5. 代码实现

下面是用go实现的代码:

import ("hash/crc32""sort""strconv"
)// Hash map bytes to uint32
type Hash func(data []byte) uint32// 包含所有的hashed keys
type Map struct {hash     Hash           //Hash 函数replicas int            //虚拟节点倍数keys     []int          //虚拟节点的哈希环hashMap  map[int]string //虚拟节点与真实节点的映射表,键是虚拟节点的哈希值,值是真实节点的名称。
}// New create a Map instance
func New(replicas int, fn Hash) *Map {m := &Map{replicas: replicas,hash:     fn,hashMap:  make(map[int]string),}if m.hash == nil {m.hash = crc32.ChecksumIEEE}return m
}func (m *Map) Add(keys ...string) {for _, key := range keys {for i := 0; i < m.replicas; i++ {// 虚拟节点在哈希环上的hash值hash := int(m.hash([]byte(strconv.Itoa(i) + key)))m.keys = append(m.keys, hash)// 虚拟节点和真实节点的映射m.hashMap[hash] = key}}sort.Ints(m.keys)
}func (m *Map) Get(key string) string {if len(m.keys) == 0 {return ""}// 要查询的key的hashhash := int(m.hash([]byte(key)))// 找到最近的虚拟节点对应的下标idxidx := sort.Search(len(m.keys), func(i int) bool {return m.keys[i] >= hash})//顺时针找到第一个匹配的虚拟节点的下标 idx,从 m.keys 中获取到对应的哈希值。如果 idx == len(m.keys),说明应选择 m.keys[0],因为 m.keys 是一个环状结构,所以用取余数的方式来处理这种情况。//m.keys[idx%len(m.keys)]获得虚拟节点的hash//根据虚拟节点的hash值获取真实节点return m.hashMap[m.keys[idx%len(m.keys)]]
}

6.总结

一致性哈希是指将「存储节点」和「数据」都映射到一个首尾相连的哈希环上,如果增加或者移除一个节点,仅影响该节点在哈希环上顺时针相邻的后继节点,其它数据也不会受到影响。

但是一致性哈希算法不能够均匀的分布节点,会出现大量请求都集中在一个节点的情况,在这种情况下进行容灾与扩容时,容易出现雪崩的连锁反应。

为了解决一致性哈希算法不能够均匀的分布节点的问题,就需要引入虚拟节点,对一个真实节点做多个副本。不再将真实节点映射到哈希环上,而是将虚拟节点映射到哈希环上,并将虚拟节点映射到实际节点,所以这里有「两层」映射关系。

引入虚拟节点后,可以会提高节点的均衡度,还会提高系统的稳定性。所以,带虚拟节点的一致性哈希方法不仅适合硬件配置不同的节点的场景,而且适合节点规模会发生变化的场景。

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

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

相关文章

MySQL分库分表的方式有哪些

目录 一、为什么要分库分表 二、什么是分库分表 三、分库分表的几种方式 1.垂直拆分 2. 水平拆分 四、分库分表带来的问题 五、分库分表技术如何选型 一、为什么要分库分表 如果一个网站业务快速发展&#xff0c;那这个网站流量也会增加&#xff0c;数据的压力也会随之而…

【Java核心能力】美团优选后端一面:网络 操作系统

欢迎关注公众号&#xff08;通过文章导读关注&#xff1a;【11来了】&#xff09;&#xff0c;及时收到 AI 前沿项目工具及新技术的推送&#xff01; 在我后台回复 「资料」 可领取编程高频电子书&#xff01; 在我后台回复「面试」可领取硬核面试笔记&#xff01; 文章导读地址…

如何注册midjourney账号

注册Midjourney账号比较简单&#xff0c;准备好上网工具&#xff0c;进入官网 Midjourney访问地址&#xff1a; https://www.midjourney.com/ 目前没有免费使用额度了&#xff0c;会员最低 10 美元/月&#xff0c;一般建议使用30美元/月的订阅方案。了解如何订阅可以查看订阅…

实战环境-Activiti7从入门到专家(4)

背景 对于activiti7 已经有了感性认知&#xff0c;并且已经获得了源代码&#xff0c;梳理了核心的API。后面还有大量的内容&#xff0c;包括BPMN规范的落地&#xff0c;但是我们不能只停留在理论层次&#xff0c;需要从实际罗德的内容展开&#xff0c;因此需要构建实战环境。 …

Ubuntu20.04配置Kinect 2.0驱动安装和ROS环境下配置以及录制bag包和制作ORB-SLAM数据集

目录 1. 安装libfreenect21.1 下载官方文件1.2 安装build工具1.3 安装libusb1.4 安装urboJPEG1.5 安装OpenGL1.6 安装OpenCL1.7 安装OpenNI1.8 进入libfreenect2 文件夹&#xff0c;编译安装1.9 设定udev rules1.10 测试 2. 配置ROS环境2.1 下载iai_kinect2包并安装2.2 相机上电…

十六进制前缀为Ox还是0x???

16进制的前缀是0x&#xff0c;数字零和英文字母X。 十六进制&#xff08;英文名称&#xff1a;Hexadecimal&#xff09;&#xff0c;是计算机中数据的一种表示方法。同我们日常生活中的表示法不一样。它由0-9&#xff0c;A-F组成&#xff0c;字母不区分大小写。与10进制的对应…

网络安全---RSA公钥加密与签名

实验项目&#xff1a;RSA公钥加密与签名实验 1.实验目的 本实验的学习目标是让学生获得 RSA 算法的动手经验。 通过课堂学习&#xff0c;学生应该已经了解 RSA 算法的理论部分&#xff0c; 知道在数学上如何生成公钥、私钥以及如何执行加密、解密和签名生成、验证。 通过使用…

数字图像处理与交叉学科中名词的拧巴

特征提取 图像处理——对图像、目标或特征点进行定量描述的方法及过程。 模式识别——对原特征进行特征变换&#xff0c;从高维空间到低维空间映射。 特征向量 模式识别、图像处理——一个观测包括多个变量&#xff0c;样本的多个特征组成特征向量。 线性代数——特征值对应的…

构建强健身体的未来:健身管理平台微服务架构解析

在现代社会&#xff0c;人们越来越关注健康和身体素质的提升。健身管理平台应运而生&#xff0c;为用户提供个性化的健身计划、监测和管理工具。微服务架构作为一种灵活且可扩展的系统设计方法&#xff0c;为健身管理平台提供了高效、可靠的基础。 1. 概述健身管理平台微服务架…

python|sort_values()排序

sort_value()可以用来对值&#xff08;比如说年龄&#xff09;进行排序 根据 ‘Age’ 列进行升序排序&#xff0c;如果 ‘Age’ 相同则根据 ‘Name’ 列进行降序排序 df_sorted_multi df.sort_values(by[Age, Name], ascending[True, False]) print(df_sorted_multi)

正则表达式 速成

正则表达式的作用 正则表达式&#xff0c;又称规则表达式,&#xff08;Regular Expression&#xff0c;在代码中常简写为regex、regexp或RE&#xff09;&#xff0c;是一种文本模式&#xff0c;包括普通字符&#xff08;例如&#xff0c;a 到 z 之间的字母&#xff09;和特殊字…

Tailwind 4.0 即将到来:前端开发的“速度与激情”

随着前端开发技术的不断进步&#xff0c;我们每天都在寻找更快、更简洁的解决方案来提升我们的开发效率和用户体验。今天&#xff0c;我要为大家介绍一项令人振奋的新技术进展——Tailwind 4.0的来临&#xff01; 对于经常使用Tailwind的朋友们来说&#xff0c;这个消息无疑是激…

规则引擎之LiteFlow应用

官网地址&#xff1a;LiteFlow DEMO 整体结构 1.引入maven依赖 <dependency><groupId>com.yomahub</groupId><artifactId>liteflow-spring-boot-starter</artifactId><version>2.11.4.2</version> </dependency> 2. 配置yml …

mysql数据库备份脚本.sh

mysql数据库备份脚本.sh #!/bin/bash #备份路径 BAKDIR/home/peter/date %Y-%m-%d #要备份的数据库 MYSQLDBtest #使用哪个用户备份 MYSQLUSRroot #判断是否是root用户执行此脚本 if [ $UID -ne 0 ] then echo This scripts must use the root user!!! sleep 2 exit…

HDFS [MSST‘10] 论文阅读笔记

原论文:The Hadoop Distributed File System (MSST’10) HDFS关键技术要点概览 设计目标:HDFS旨在可靠地存储大型数据集,并以高带宽流式传输这些数据集到用户应用程序。它通过在大量服务器上分布存储和计算资源,使得资源可以随着需求的增长而扩展,同时保持经济高效。架构组…

24年权威数学建模报名通知汇总(含妈妈杯、国赛、美赛、电工杯、数维杯、五一数模、深圳杯......)

1、MathorCup比赛 报名时间&#xff1a;2024年4月11日中午12点&#xff08;周四&#xff09; 比赛开始时间&#xff1a;2024年4月12日上午8时&#xff08;周五&#xff09; 比赛结束时间&#xff1a;2024年4月16日上午9时&#xff08;周二&#xff09; 报名费用&#xff1a…

HarmonyOS 开发-Worker子线程中解压文件

介绍 本示例介绍在Worker 子线程使用ohos.zlib 提供的zlib.decompressfile接口对沙箱目录中的压缩文件进行解压操作&#xff0c;解压成功后将解压路径返回主线程&#xff0c;获取解压文件列表。 效果图预览 使用说明 点击解压按钮&#xff0c;解压test.zip文件&#xff0c;显…

基于springboot实现医院管理系统项目【项目源码+论文说明】

基于springboot实现医院管理系统演示 摘要 随着信息互联网信息的飞速发展&#xff0c;医院也在创建着属于自己的管理系统。本文介绍了医院管理系统的开发全过程。通过分析企业对于医院管理系统的需求&#xff0c;创建了一个计算机管理医院管理系统的方案。文章介绍了医院管理系…

RabbitMQ如何保证消息的幂等性???

在RabbitMQ中&#xff0c;保证消费者的幂等性主要依赖于业务设计和实现&#xff0c;而非RabbitMQ本身提供的一种直接功能。 在基于Spring Boot整合RabbitMQ的场景下&#xff0c;要保证消费者的幂等性&#xff0c;通常需要结合业务逻辑设计以及额外的技术手段来实现。以下是一个…

Redis的双写一致性问题

双写一致性问题 1.先删除缓存或者先删除数据库都可能出现脏数据。 2.删除两次缓存&#xff0c;可以在一定程度上降低脏数据的出现。 3.延时是因为数据库一般采用主从分离&#xff0c;读写分离。延迟一会是让主节点把数据同步到从节点。 1.读写锁保证数据的强一致性 因为一般放…