Java三齐王乱点兵算法_韩信的大招:一致性哈希算法

2024-01-30 17:50

本文主要是介绍Java三齐王乱点兵算法_韩信的大招:一致性哈希算法,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

韩信点兵的成语来源淮安民间传说。常与多多益善搭配。寓意越多越好。我们来看下主公刘邦和韩信大将军的对话。

刘邦:“你觉得我可以带兵多少?”

韩信:“最多十万。”

刘邦不解的问:“那你呢?”

韩信自豪地说:“越多越好,多多益善嘛!

假如刘邦现在给了韩信一千个士兵,需要大致均匀分成三组。士兵的编号是六位数,从 1-100000 随机分配。比如第一个士兵的值是 245,第二个士兵的编号是 82593,其他士兵类似。那么如何对士兵进行分配呢?

刘邦:韩将军,你看这些士兵怎么分配好呢?

韩信:这还不简单,我的一技能就能搞定。

一技能:哈希算法

分组

韩信的一技能哈希算法:将士兵的编号 num 值当做一个哈希值,再和总做小组数 N 做取余操作,得出的结果在 0 到 N - 1 之间,这个士兵就属于那个组。

如下图所示,每来一个士兵都有一个六位的 hash 值(也可以称作编号),然后被韩信用除以 3 取余数的方式分配到三个组。比如第一组中的编号为 123456 的士兵,除以 3 之后,整除,余数为 0,所以分配到第一组。

d881b1b7c057b48c8fbf2f0341617cf9.png

哈希算法

查找士兵

现在已经分好组了,假如想找到编号为 666666 的士兵该怎么找?首先将 666666 除以 3,得到余数 0,说明在第一个组,然后去第一个组里面找就可以了。

这里有小伙伴可能会问,为什么不是把所有士兵放到一个组?

因为一个组太大了,影响行军速度。映射到互联网架构中,就是通过增加节点从而减小单节点的负载压力。

哈希分组弊端

刘邦看了这个一技能后,大呼:

韩将军真是厉害。

哈希算法看起来很完美,那我再给你五百士兵,需要分成四个组怎么办?

这时,韩信的副将说话了:

这还不简单,再用 4 取余不就好了吗?

刘邦摸着下巴思索片刻后,对副将说:

这个方案可行,但很多士兵都被重新分组了,刚刚建立的团队友情就被分解了。

我们来看下刘邦为什么觉得方案不可行。

比如原来分配到一组的编号为 3 的士兵,当分成四组的时候,通过公式计算:3%4=3,所以会分配到到第四组。

依次类推,会发现很多士兵进行了重新分配,只有小部分不会变换分组,比如 1,2,12 不会被重新分组。

韩信对着刘邦点点头,对着主公说道:

主公,您说得没错,这就是我的一技能的弱点所在。

不过我还有一个技能:一致性哈希。

二技能:一致性哈希

哈希环

一致性哈希算法也用了取模运算,但是它与哈希算法不同的地方:

哈希算法:对节点的数量进行取模运算。

一致性哈希算法:对 2^32 进行取模运算。

可以想象一下,一致性哈希算法,是将整个哈希值空间组成了一个虚拟的圆环,也就是哈希环。

如下图,把 3 个组映射到固定大小为 2^32 的哈希环中。三个组一共将整个环分成了三个区域,C-A(第一组)、A-B(第二组)、B-C(第三组)。如下图所示:

0090da1629b89b6ae9014aff21b77e9d.png

分成三组

第一组负责存储落在 C-A 区间内的数据。

第二组负责存储落在 A-B 区间内的数据。

第三组负责存储落在 B-C 区间内的数据。

士兵分配

假定编号为 9527 的士兵,进行哈希运算后,落到 C-A 区域。如下图所示:

27d3e532c86a0334d2c0cd03eedf29f2.png

士兵所站位置

第二步,让这个士兵顺时针往前走,遇到的第一个节点 A 就是他所在的组了。如下图所示:

a29854bbdc0dadcf8efd3ba084968520.png

顺时针遇到第一个节点

增加分组

目前三个节点的时候,假定编号为 89757 的士兵经过哈希运算后,分配到了 B-C 区域(第三组),也就是属于 C 节点管控。如下图所示:

a3a58948787c014b4a1709841defc97c.png

属于 C 节点

回到刘邦刚问的问题,如果分组变成四组,该怎么进行士兵分配。

如下图所示,增加一个节点 D,原来的区域 B-C 变成了区域 B-D(第三组) 和 D-C(第四组)。

5436abb9d727e3fe3869709068431934.png

增加 D 节点

那么这名士兵属于哪个节点管控呢?如下图所示,士兵顺时针往前走,先走到了 D 节点,所以属于 D 节点管控。虽然还是属于第三组,但是这名士兵的领导者已经变了:由 C 变成了 D。

4fa427dc7aa4cf236c7604d297dbd932.png

领导者变了

从上面的变化来看,只有 B-C 区域中的部分数据会进行迁移:B-D 之间的数据会由 C 节点迁移到 D 节点。

而其他数据不受影响,也不用进行迁移。而且节点越多,需要迁移的数据就越少。这就是多多益善了~

刘邦看了后,大赞韩信:

不亏是大将军,萧何当时月下追你,值了!

哈希环缺陷

萧何看了韩信画的哈希环后,觉得有些不对劲,思索片刻后,对韩信说:

将军,你这个哈希环上的节点分布不太均匀啊,你看第三组和第四组的的区域好小啊。

萧何说得没错,确实存在这个问题,放到互联网架构中,就存在如下问题:

节点分布不均匀,导致业务对节点的访问冷热不均。

韩信眼中充满着赞赏,知我者莫若萧何。然后胸有成竹地说道:

你说得没错,不过我还有一个技能,虚拟节点映射。

三技能:虚拟节点

一般虚拟节点比物理节点要多,并相对均匀地分布在哈希环上。如下图所示,12 个虚拟节点 N1~N12,相对均匀地分布在虚拟节点上。如果有士兵属于 N2/N3/N4 中的某一个,都会重新映射到 A 节点,依次类推,N5/N6/N7 属于 B 节点的虚拟节点映射。

baa5fd4f457c4269aeb3f473c27f1b35.png

虚拟节点

我们来看下萧何的提出的问题,真实的 B-D 区域比较小,用虚拟节点后,N5/N6/N7 属于 B 节点,N8/N9/N10 属于 D 节点,他们分到的虚拟节点一样多,而且区域大致相等。所以士兵的分配也比较均匀。

萧何看了韩信的三技能后,直呼:妙哉妙哉!

总结

本篇通过韩信点兵的故事,然后从故事中衍生出刘邦、韩信、萧何的对话,来讲解士兵的分组的问题。现在对故事中的知识点做一个总结:

哈希算法会带来增加或删除节点时,

数据迁移量太大的问题。

一致性哈希算法

降低了数据迁移量。

节点较少

,哈希环上每个节点实际占据的区间大小不一,最终导致业务对节点的访问

冷热不均。

引入

虚拟节点映射解决了分布不均问题。

节点

越多时,

使用哈希

算法时,需要迁移的数据就

越多,而使用一致性哈希算法,迁移的数据就

越少。

一致性哈希算法本质上是一种

路由寻址算法,适合简单的路由寻址场景。

一致性哈希算法常用在负载均衡的架构设计中。

这篇关于Java三齐王乱点兵算法_韩信的大招:一致性哈希算法的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/661055

相关文章

Java的栈与队列实现代码解析

《Java的栈与队列实现代码解析》栈是常见的线性数据结构,栈的特点是以先进后出的形式,后进先出,先进后出,分为栈底和栈顶,栈应用于内存的分配,表达式求值,存储临时的数据和方法的调用等,本文给大家介绍J... 目录栈的概念(Stack)栈的实现代码队列(Queue)模拟实现队列(双链表实现)循环队列(循环数组

Java中Switch Case多个条件处理方法举例

《Java中SwitchCase多个条件处理方法举例》Java中switch语句用于根据变量值执行不同代码块,适用于多个条件的处理,:本文主要介绍Java中SwitchCase多个条件处理的相... 目录前言基本语法处理多个条件示例1:合并相同代码的多个case示例2:通过字符串合并多个case进阶用法使用

Java中的Lambda表达式及其应用小结

《Java中的Lambda表达式及其应用小结》Java中的Lambda表达式是一项极具创新性的特性,它使得Java代码更加简洁和高效,尤其是在集合操作和并行处理方面,:本文主要介绍Java中的La... 目录前言1. 什么是Lambda表达式?2. Lambda表达式的基本语法例子1:最简单的Lambda表

Java中Scanner的用法示例小结

《Java中Scanner的用法示例小结》有时候我们在编写代码的时候可能会使用输入和输出,那Java也有自己的输入和输出,今天我们来探究一下,对JavaScanner用法相关知识感兴趣的朋友一起看看吧... 目录前言一 输出二 输入Scanner的使用多组输入三 综合练习:猜数字游戏猜数字前言有时候我们在

Spring Security+JWT如何实现前后端分离权限控制

《SpringSecurity+JWT如何实现前后端分离权限控制》本篇将手把手教你用SpringSecurity+JWT搭建一套完整的登录认证与权限控制体系,具有很好的参考价值,希望对大家... 目录Spring Security+JWT实现前后端分离权限控制实战一、为什么要用 JWT?二、JWT 基本结构

java解析jwt中的payload的用法

《java解析jwt中的payload的用法》:本文主要介绍java解析jwt中的payload的用法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Java解析jwt中的payload1. 使用 jjwt 库步骤 1:添加依赖步骤 2:解析 JWT2. 使用 N

springboot项目如何开启https服务

《springboot项目如何开启https服务》:本文主要介绍springboot项目如何开启https服务方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录springboot项目开启https服务1. 生成SSL证书密钥库使用keytool生成自签名证书将

Java实现优雅日期处理的方案详解

《Java实现优雅日期处理的方案详解》在我们的日常工作中,需要经常处理各种格式,各种类似的的日期或者时间,下面我们就来看看如何使用java处理这样的日期问题吧,感兴趣的小伙伴可以跟随小编一起学习一下... 目录前言一、日期的坑1.1 日期格式化陷阱1.2 时区转换二、优雅方案的进阶之路2.1 线程安全重构2

Java中的JSONObject详解

《Java中的JSONObject详解》:本文主要介绍Java中的JSONObject详解,需要的朋友可以参考下... Java中的jsONObject详解一、引言在Java开发中,处理JSON数据是一种常见的需求。JSONObject是处理JSON对象的一个非常有用的类,它提供了一系列的API来操作J

SpringBoot多数据源配置完整指南

《SpringBoot多数据源配置完整指南》在复杂的企业应用中,经常需要连接多个数据库,SpringBoot提供了灵活的多数据源配置方式,以下是详细的实现方案,需要的朋友可以参考下... 目录一、基础多数据源配置1. 添加依赖2. 配置多个数据源3. 配置数据源Bean二、JPA多数据源配置1. 配置主数据