分布式与一致性协议之一致哈希算法(二)

embedded/2025/1/15 23:32:28/

一致哈希算法

使用哈希算法有什么问题

通过哈希算法,每个key都可以寻址到对应的服务器,比如,查询key是key-01,计算公式为hash(key-01)%3,警告过计算寻址到了编号为1的服务器节点A,如图所示。
在这里插入图片描述

但如果服务器数量发生变化,我们基于新的服务器数量来执行哈希算法时,就会出现路由寻址失败的秦广,导致Proxy无法找到之前寻址到的那个服务器节点,这是为什么呢?
想象以下,加入3个节点不能满足当前的业务虚要,这时我们增加了一个节点,节点数量从3变为4,那么之前的hash(key-01)%3=1就变成了hash(key-01)%4=X,因为取模运算发生了变化,所以这个X大概率不是1(可能是2),这时你再查询,就会找不到数据,因为key-01对应的数据存储再节点A上,而不是节点B上,如图所示。
在这里插入图片描述

同样的道理,如果我们需要下线1个服务器节点(也就是缩容),也会存在类似的问题。而解决这个问题的办法在于我们要迁移数据,基于新的计算公式hash(key-01)%4来重新对数据和节点做映射。需要注意的是,数据的迁移成本是非常高的。
为了便于理解,我们用一个示例来说明。对于1000万个key 的3节点KV存储,如果我们增加1个节点,即3节点集群变为4节点集群,则需要迁移75%的数据,如代码所示

package mainimport (
"flag"
"fmt"
)var keysPtr = flag.Int("keys", 10000000, "key number")
var nodesPtr = flag.Int("nodes", 3, "node number of old cluster")
var newNodesPtr = flag.Int("new-nodes", 4, "node number of new cluster")func hash(key int, nodes int) int {
return key % nodes
}func main() {flag.Parse()
var keys = *keysPtr
var nodes = *nodesPtr
var newNodes = *newNodesPtrmigrate := 0
for i := 0; i < keys; i++ {
if hash(i, nodes) != hash(i, newNodes) {
migrate++
}
}migrateRatio := float64(migrate) / float64(keys)
fmt.Printf("%f%%\n", migrateRatio*100)
}
go run ./hash.go -keys 10000000 -nodes 3 -new-nodes 4
74.999980%

从示例代码的输出可以看到,迁移成本非常高昂,这在实际生产环境中也是无法想象的

如何使用一致哈希算法实现哈希寻址

一致哈希算法也采用取模运算,但与哈希算法是对节点的数量进行取模不同,一致哈希算法是对2 ^ 32进行取模。你可以想象以下,一致哈希算法是将整个哈希空间组织成一个虚拟的圆环,也就是哈希换,如图所示,在这里插入图片描述
从图中可以看到,哈希环的空间是按顺时针方向组织的,圆环的正上方点的点代表0,0点右侧的第一个点代表1,以此类推,2、3、4、5、6…知道2 ^ 32-1,也就是说0点左侧的第一个点代表2^32-1.在一致哈希算法中,你可以通过执行哈希算法(为了演示方便,假设哈希算法函数为c-hash())将节点映射到哈希环上,比如选择节点的主机名作为参数进行c-hash()函数运算,确定每个节点在哈希环上的位置,如图所示。在这里插入图片描述
当需要对指定的key的值进行读写的时候,你可以通过下面两步进行寻址:

  • 1.首先,将key作为参数进行c-hash()函数运算,计算哈希值,并确定此key在环上的位置
  • 2.然后,从这个位置沿着哈希环顺时针"行走",遇到的第一节点就是key对应的节点
    为了更好地理解如何通过一致哈希寻址,用一个示例来说明。假设key-01、key-02、key-03 3个key经过哈希算法c-hash()函数计算后,在哈希环上的位置如图所示。
    在这里插入图片描述

那么根据一致哈希算法,key-01将寻址到节点A,key-02将寻址到节点B,key-03将寻址到节点C.你可能会问,那一致哈希是如何避免哈希算法的问题的呢?
假设现在有一个节点故障了(比如节点C),如图所示。在这里插入图片描述

可以看到,key-01和key-02不会受到影响,而key-03得寻址将被重定位到A.一般来说,在一致哈希算法中,如果某个节点宕机不可用了,那么受影响的数据仅仅是会寻址到此节点和前一节点之间的数据。比如当节点C宕机时,受影响的数据是会寻址到节点B和节点C之间的数据(例如key-03),而寻址到其他哈希环空间的数据(例如key-01)不会受到影响。如果此时集群不能满足业务的需求,则需要扩容一个节点(也就是增加一个节点,比如D),如图所示.
在这里插入图片描述

可以看到,key-01、key-02不会受到影响,而key-03的寻址被重定位到新节点D.一般而言,在一致哈希算法中,如果增加一个节点,受影响的数据仅仅是会寻址到新节点和前一节点之间的数据,其他数据则不会受到影响。


http://www.ppmy.cn/embedded/32566.html

相关文章

软件ip地址怎么改到别的城市去

随着互联网的快速发展&#xff0c;越来越多的业务场景需要频繁地更换IP地址。比如&#xff0c;我们需要将软件IP地址改到别的城市&#xff0c;那么&#xff0c;对于刚接触这一领域的用户来说&#xff0c;可能不知道软件IP地址怎么改到别的城市&#xff0c;下面我们一起了解一下…

【实验】根据docker部署nginx并且实现https

环境准备 systemctl stop firewalld setenforce 0 安装docker #安装依赖包 yum -y install yum-utils device-mapper-persistent-data lvm2 #设置阿里云镜像 yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo #安装最新版…

OceanBase 分布式数据库【信创/国产化】- OceanBase 数据库代理概述

本心、输入输出、结果 文章目录 OceanBase 分布式数据库【信创/国产化】- OceanBase 数据库代理概述前言OceanBase 数据更新架构OceanBase 数据库代理概述为什么需要 ODP?ODP 特性OceanBase 分布式数据库【信创/国产化】- OceanBase 数据库代理概述 编辑 | 简简单单 Online zu…

深入浅出MySQL-06-【索引的设计和使用】

文章目录 前言1.索引概述2.设计索引的原则3.索引设计的误区4.索引设计的一般步骤5.BTREE索引和HASH索引6.索引在MySQL 8.0中的改进6.1.不可见索引6.2.倒序索引 7.总结 前言 环境&#xff1a; Windows11MySQL-8.0.35 1.索引概述 所有MySQL列类型都可以被索引&#xff0c;对相…

数据结构与算法-单向环形链表与约瑟夫问题(续思路与代码)

上一篇写的单向环形链表与约瑟夫问题简介和举例&#xff0c;这篇写思路和代码~ 目录 3.思路 3.1创建环形链表&#xff1a; 3.2遍历环形链表&#xff1a; 3.3产生出圈序号&#xff1a; 4.代码 4.1在构建环形链表时添加节点&#xff1a; 4.2遍历环形链表&#xff1a; 4.3产…

MongoDB分片集群搭建

MongoDB分片集群搭建 如果不清楚什么是分片集群&#xff0c;可以看我上一篇发布的文章MongoDB分片集群详解 环境信息 以下是我在测试环境中虚拟机的配置&#xff0c;如果你的虚拟机ip不同可以对应的更改&#xff0c;但是要确保这三台虚拟机之间可以ping通 #操作系统&#xf…

Python量化炒股的数据信息获取

Python量化炒股的数据信息获取 在炒股实战中&#xff0c;为了提高选股的质量&#xff0c;往往需要获取更多关注个股的数据信息&#xff0c;如个股的员工情况&#xff0c;管理人员任职情况&#xff0c;大股东信息&#xff0c;股份质押和冻结信息以及分红送股信息等。 获取上市…

Assembly via Remainders题解

题目来源&#xff1a;Problem - C - Codeforces 在打比赛时写出来ac了&#xff0c;但是代码太弱了&#xff0c;等到后台重新判断时被hack&#xff08;斩&#xff09;了&#xff0c;因此重新写了一份代码。 题目描述&#xff1a;给定一段a序列&#xff0c;在求出n个数的b序列且满…