一致性哈希算法原理
文章目录
- 前言
- 正文
- 一、抛砖引玉,简单Hash算法的短板
- 二、一致性Hash算法的基本概念
- 2.1 一致性Hash算法本质也是取模
- 2.2 便于理解的抽象,哈希环
- 2.3 服务器如何映射到哈希环上
- 2.4 对象如何映射到哈希环上,并关联到对应的机器
- 三、一致性Hash算法在增加或减少机器时的骚操作
- 3.1 服务器数量减少
- 3.2 服务器数量增加
- 四、数据倾斜、机器负载的处理
- 4.1 数据倾斜的体现
- 4.2 机器负载的体现
- 4.3 处理方案,增加虚拟节点
- 五、Java代码模拟算法
- 5.1 定义哈希算法接口
- 5.2 简单哈希算法
- 5.3 一致性哈希算法(不包含虚拟节点)
- 5.4 一致性哈希算法(包含虚拟节点)
- 5.5 测试
- 5.6 测试结果
- 六、一致性哈希算法的应用场景
前言
首先我们学习和了解一个知识时,可能会先下意识搜索一下它的基本概念。所以我先百度了一下。
百度给出的概念,可以说是很明确了:
一致性哈希算法在1997年由麻省理工学院提出,是一种特殊的哈希算法,目的是解决分布式缓存的问题。
在移除或者添加一个服务器时,能够尽可能小地改变已存在的服务请求与处理请求服务器之间的映射关系。
一致性哈希解决了简单哈希算法在分布式哈希表( Distributed Hash Table,DHT) 中存在的动态伸缩等问题 。
正文
根据百度,我们可以知道,所谓一致性Hash算法,是一种特殊的Hash算法。
那么学习的捷径就出来了,我们可以对比学习,先来看看Hash算法,然后再去研究它对于解决动态伸缩问题上的短板究竟是什么。
一、抛砖引玉,简单Hash算法的短板
我们先假设出这样一个场景:
当前有3台机器
node1、node2、node3,是我们用来存储缓存的。业务数据缓存目前假设有100万个key。
我们的需求是,将这100万个key 尽可能均匀的存储到这3台机器上。
效果图如下:

当我们采取简单Hash算法时,对所有的key值进行hash计算,获取到一个hash值,再取模于3(3台机器,所以取模于3)。
这样就能保证所有算出来的结果一定是 0、1、2 这3个数,从而对应到我们的3台机器,就可以解决以上的问题。如下图所示:

那么问题来了,在分布式场景中,我们的机器会有数量调整的情况。
就好比电商相关的项目,在618、双11等购物狂欢节时,就需要临时增加机器,然后等高峰期过后,又需要减少节点。
这种时候,对机器数量取模,就不好使了。
假设原先有3台机器,存值时使用的是取模于3,在用的时候,有一台挂了,取值时取模于2,如下图:

这种时候,由于node3挂掉,取模模于2,自然会有很多缓存无法命中,也就是失效。
那么大量缓存同时失效,就可以恭喜你了,喜提缓存雪崩,整个缓存系统不可用,这也就是简单Hash算法无法处理的短板,也正是一致性Hash算法所解决的问题之一。
二、一致性Hash算法的基本概念
它的基本概念其实就和我百度出来的相同。可以翻到本文前言,再重新读一遍,理解一下。
本小节内容主要是基于百度出来的基本概念,进行图文讲解。
2.1 一致性Hash算法本质也是取模
一致性Hash算法,本质上也是取模运算,只是与简单Hash算法不同,它是对 2 的 32 次方 取模。
原因如下:
我们都知道IPv4地址,是由 4 段 8位二进制组成的,因为书写方便的问题,将二进制转换为十进制,例如如下地址:
而这个地址的大小范围则是 [0, 2的32次方),所以取模的值可以固定下来,能够保证每个IP地址有唯一的映射。
2.2 便于理解的抽象,哈希环
上一小节提到,IP地址的范围是 [0, 2的32次方),如果我们将所有的值抽象成环,正上方为0,以顺时针排列。
将所有的值抽象为圆周上的点,那么可以获得如下的哈希环:

2.3 服务器如何映射到哈希环上
假设现在有3台机器,分别是 nodeA 、nodeB 、nodeC,我们要把他们映射到哈希环中。
首先使用哈希算法对机器的IP地址进行计算,随后再取模,得到 A、B、C 这3个值。随后根据计算结果,映射到哈希环上。

2.4 对象如何映射到哈希环上,并关联到对应的机器
假设有4个对象,需要存起来。
对象计算时的hash函数可以和服务器节点的函数不同,但需要保证计算结果在环的范围内。
计算的结果分别是 H1,H2,H3,H4,将他们先映射到Hash环上。

然后从0开始,顺时针转圈,当对象计算出的结果蓝色H,第一次遇到绿色(机器),就存到该机器上。关联后的结果如下:

H2和H4存到了 B 机器上;H1存到了C机器上,H3存到了A机器上
本质是将原本单个点的Hash映射,转变成了环上的某个片段的映射,也就是百度百科中提到的:
在移除或者添加一个服务器时,能够尽可能小地改变已存在的服务请求与处理请求服务器之间的映射关系。
这一原理的实现,也就在于此。我们接着往下看。
三、一致性Hash算法在增加或减少机器时的骚操作
3.1 服务器数量减少
比如C机器挂了,H1会存到A机器上

3.2 服务器数量增加
比如增加机器D,H2会存到D机器上

四、数据倾斜、机器负载的处理
但凡使用了Hash算法,就可能存在数据倾斜的问题(这里我们不考虑哈希冲突)。上述例子中,为了方便演示,基本使用了比较均衡的散列示例。
这里我们需要考虑两个问题:
- 数据倾斜,也就是Hash散列不均匀,可能给一个机器存储过多的对象数据,而有的机器却一个都不存储;
- 机器负载不均衡,在增加机器时,不能很好的分摊机器负载或只分担很少机器的负载,在现象上看,其实勉强也算是一种数据倾斜的问题;
4.1 数据倾斜的体现
很多对象集中映射到某一台或几台机器,其他机器数据映射很少甚至于没有。
可以看到很多数据都映射到了B机器,而A 、C 机器上映射的数据很少。

4.2 机器负载的体现
在数据倾斜发生时,本身就是机器负载不均衡的一种体现,但本小节提到的,是另一种场景。
在我们增加机器时,新增的机器不能很好的分担其他机器的负载,这也是一个问题。
比如,为了帮忙分担负载,增加了机器D:

但是D映射的位置比较尴尬,没有帮助B 分担到负载。
又或者说另一种情况,A 机器现在也有很多数据存储,我们新增机器D:

D的出现,帮B分担了部分压力,但是对A没有任何影响。
4.3 处理方案,增加虚拟节点
为了处理以上的两个问题,可以引入虚拟节点的概念。
所谓虚拟节点,就是针对每个实际机器,计算多个映射点。
比如:
针对nodeA 计算的虚拟节点有 A#1 、A#2 、A#3 ,实际节点是 A
针对nodeB 计算的虚拟节点有 B#1 、B#2 、B#3,实际节点是 B
针对nodeC 计算的虚拟节点有 C#1 、C#2 、C#3,实际节点是 C
他们分布在哈希环上之后,就如下图所示:

使用虚拟节点时,可以看到当虚拟节点越多,也就越不容易出现数据倾斜。
然后我们再依据虚拟节点对真实节点做一套转换即可。
也就是原先找节点的逻辑基本不变,只是在找到虚拟节点时,一律定位到实际机器上。
比如,我们找到数据H3 在 A#2虚拟节点上,就在此定位到A机器真实的节点A上。
五、Java代码模拟算法
Java 版本使用Java 9
涉及到的类文件有:

5.1 定义哈希算法接口
定义接口,用以实现3种哈希算法
package com.example.demo;import java.util.List;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;/*** 哈希算法接口** @author feng*/
public interface HashAlgorithm {/*** 哈希算法** @param clients 客户端集合* @return 服务端地址和客户端地址列表的映射*/SortedMap<String, List<String>> hash(Set<String> clients);/*** 服务器的编号、地址*/SortedMap<Integer, String> SERVER_ADDRESS_MAP = new TreeMap<>();
}
5.2 简单哈希算法
package com.example.demo;import java.util.*;/*** 简单Hash算法** @author feng*/
public class GeneralHashAlgorithm implements HashAlgorithm {private final int serverCount;public GeneralHashAlgorithm(int serverCount) {this.serverCount = serverCount;}@Overridepublic SortedMap<String, List<String>> hash(Set<String> clients) {SortedMap<String, List<String>> resultMap = new TreeMap<>();for (String client : clients) {// 执行hash,获取值int hashCode = Math.abs(client.hashCode());// 计算索引int index = hashCode % serverCount;// 获取选中的服务器地址String serverAddress = SERVER_ADDRESS_MAP.get(index);System.out.printf("客户端%s 选中了服务端序号为%s,地址为%s \r\n", client, index, serverAddress);List<String> newArrayList = resultMap.getOrDefault(serverAddress, new ArrayList<>());newArrayList.add(client);resultMap.put(serverAddress, newArrayList);}return resultMap;}
}
5.3 一致性哈希算法(不包含虚拟节点)
package com.example.demo;import java.util.*;/*** 一致性哈希算法-不包括虚拟节点** @author feng*/
public class ConsistencyExcludeVirtualNodeHashAlgorithm implements HashAlgorithm {@Overridepublic SortedMap<String, List<String>> hash(Set<String> clients) {SortedMap<String, List<String>> resultMap = new TreeMap<>();// 哈希散列服务端地址SortedMap<Integer, String> hashServerMap = serverHash();// 处理客户端地址for (String client : clients) {int clientHashCode = Math.abs(client.hashCode());// 从服务端地址中查找能够处理的服务器节点,tailMap表示返回此映射中键大于或等于key的部分的mapSortedMap<Integer, String> tempSortedMap = hashServerMap.tailMap(clientHashCode);// 从当前节点,顺时针转完一整圈,回到0点,仍未发现能够处理的服务器if (tempSortedMap.isEmpty()) {// 取哈希环中的第一个服务器Integer firstKey = hashServerMap.firstKey();String firstAddress = hashServerMap.get(firstKey);System.out.printf("客户端%s 选中了服务端序号为%s,地址为%s \r\n", client, firstKey, firstAddress);List<String> newArrayList = resultMap.getOrDefault(firstAddress, new ArrayList<>());newArrayList.add(client);resultMap.put(firstAddress, newArrayList);} else {// 从哈希环取符合条件的服务器Integer firstKey = tempSortedMap.firstKey();String firstAddress = hashServerMap.get(firstKey);System.out.printf("客户端%s 选中了服务端序号为%s,地址为%s \r\n", client, firstKey, firstAddress);List<String> newArrayList = resultMap.getOrDefault(firstAddress, new ArrayList<>());newArrayList.add(client);resultMap.put(firstAddress, newArrayList);}}return resultMap;}private SortedMap<Integer, String> serverHash() {SortedMap<Integer, String> hashServerMap = new TreeMap<>();SERVER_ADDRESS_MAP.forEach((k, v) -> {int serverAddressHashCode = Math.abs(v.hashCode());hashServerMap.put(serverAddressHashCode, v);});return hashServerMap;}
}
5.4 一致性哈希算法(包含虚拟节点)
package com.example.demo;import java.util.*;/*** 一致性哈希算法-包括虚拟节点** @author feng*/
public class ConsistencyIncludeVirtualNodeHashAlgorithm implements HashAlgorithm {/*** 虚拟节点个数*/private final int virtualNodeCount;public ConsistencyIncludeVirtualNodeHashAlgorithm(int virtualNodeCount) {this.virtualNodeCount = virtualNodeCount;}@Overridepublic SortedMap<String, List<String>> hash(Set<String> clients) {SortedMap<String, List<String>> resultMap = new TreeMap<>();// 哈希散列服务端地址,增加虚拟节点映射SortedMap<Integer, String> hashServerMap = serverHash();for (String client : clients) {int clientHashCode = Math.abs(client.hashCode());// 从服务端地址中查找能够处理的服务器节点,tailMap表示返回此映射中键大于或等于key的部分的mapSortedMap<Integer, String> tempSortedMap = hashServerMap.tailMap(clientHashCode);// 从当前节点,顺时针转完一整圈,回到0点,仍未发现能够处理的服务器if (tempSortedMap.isEmpty()) {// 取哈希环中的第一个服务器Integer firstKey = hashServerMap.firstKey();String firstAddress = hashServerMap.get(firstKey);System.out.printf("客户端%s 选中了服务端序号为%s,地址为%s \r\n", client, firstKey, firstAddress);List<String> newArrayList = resultMap.getOrDefault(firstAddress, new ArrayList<>());newArrayList.add(client);resultMap.put(firstAddress, newArrayList);} else {// 从哈希环取符合条件的服务器Integer firstKey = tempSortedMap.firstKey();String firstAddress = hashServerMap.get(firstKey);System.out.printf("客户端%s 选中了服务端序号为%s,地址为%s \r\n", client, firstKey, firstAddress);List<String> newArrayList = resultMap.getOrDefault(firstAddress, new ArrayList<>());newArrayList.add(client);resultMap.put(firstAddress, newArrayList);}}return resultMap;}private SortedMap<Integer, String> serverHash() {SortedMap<Integer, String> hashServerMap = new TreeMap<>();SERVER_ADDRESS_MAP.forEach((k, v) -> {int serverAddressHashCode = Math.abs(v.hashCode());hashServerMap.put(serverAddressHashCode, v);// 增加虚拟节点for (int i = 0; i < virtualNodeCount; i++) {String virtualNodeName = v + "#" + i;int virtualNodeHashCode = Math.abs((virtualNodeName).hashCode());hashServerMap.put(virtualNodeHashCode, virtualNodeName);}});return hashServerMap;}
}
5.5 测试
package com.example.demo;import java.util.*;/*** 测试** @author feng*/
public class Client {static {HashAlgorithm.SERVER_ADDRESS_MAP.put(0, "11.123.32.3");HashAlgorithm.SERVER_ADDRESS_MAP.put(1, "23.43.41.1");HashAlgorithm.SERVER_ADDRESS_MAP.put(2, "192.169.21.3");}public static void main(String[] args) {Set<String> set = Set.of("10.78.12.3", "113.25.63.1", "126.12.3.8");SortedMap<String, List<String>> hash;// 简单hash算法hash = new GeneralHashAlgorithm(3).hash(set);hash.forEach((k, v) -> System.out.printf("简单hash算法-客户端地址%s已经映射到服务端%s \r\n", v, k));System.out.println();// 一致性hash算法(不包括虚拟节点)hash = new ConsistencyExcludeVirtualNodeHashAlgorithm().hash(set);hash.forEach((k, v) -> System.out.printf("一致性hash算法(不包括虚拟节点)-客户端地址%s已经映射到服务端%s \r\n", v, k));System.out.println();// 一致性hash算法(包括虚拟节点)hash = new ConsistencyIncludeVirtualNodeHashAlgorithm(3).hash(set);hash.forEach((k, v) -> {// 截取真实服务端地址String realServer = k;if (k.contains("#")) {realServer = k.substring(0, k.indexOf("#"));}System.out.printf("一致性hash算法(包括虚拟节点)-客户端地址%s已经映射到服务端%s ,真实的服务器地址是%s \r\n", v, k, realServer);});}
}
5.6 测试结果
客户端113.25.63.1 选中了服务端序号为2,地址为192.169.21.3
客户端10.78.12.3 选中了服务端序号为1,地址为23.43.41.1
客户端126.12.3.8 选中了服务端序号为1,地址为23.43.41.1
简单hash算法-客户端地址[113.25.63.1]已经映射到服务端192.169.21.3
简单hash算法-客户端地址[10.78.12.3, 126.12.3.8]已经映射到服务端23.43.41.1 客户端113.25.63.1 选中了服务端序号为1763606946,地址为192.169.21.3
客户端10.78.12.3 选中了服务端序号为1763606946,地址为192.169.21.3
客户端126.12.3.8 选中了服务端序号为47976546,地址为23.43.41.1
一致性hash算法(不包括虚拟节点)-客户端地址[113.25.63.1, 10.78.12.3]已经映射到服务端192.169.21.3
一致性hash算法(不包括虚拟节点)-客户端地址[126.12.3.8]已经映射到服务端23.43.41.1 客户端113.25.63.1 选中了服务端序号为1139178415,地址为23.43.41.1#2
客户端10.78.12.3 选中了服务端序号为632380315,地址为11.123.32.3#0
客户端126.12.3.8 选中了服务端序号为47976546,地址为23.43.41.1
一致性hash算法(包括虚拟节点)-客户端地址[10.78.12.3]已经映射到服务端11.123.32.3#0 ,真实的服务器地址是11.123.32.3
一致性hash算法(包括虚拟节点)-客户端地址[126.12.3.8]已经映射到服务端23.43.41.1 ,真实的服务器地址是23.43.41.1
一致性hash算法(包括虚拟节点)-客户端地址[113.25.63.1]已经映射到服务端23.43.41.1#2 ,真实的服务器地址是23.43.41.1
六、一致性哈希算法的应用场景
- PC框架Dubbo用来选择服务提供者
- 分布式关系数据库分库分表:数据与节点的映射关系
- LVS负载均衡调度器
- memcached 路由算法
- redis 的hash槽
相关文章:
一致性哈希算法原理
文章目录 前言正文一、抛砖引玉,简单Hash算法的短板二、一致性Hash算法的基本概念2.1 一致性Hash算法本质也是取模2.2 便于理解的抽象,哈希环2.3 服务器如何映射到哈希环上2.4 对象如何映射到哈希环上,并关联到对应的机器 三、一致性Hash算法…...
回归预测 | MATLAB实现BO-LSTM贝叶斯优化长短期神经网络多输入单输出回归预测
回归预测 | MATLAB实现BO-LSTM贝叶斯优化长短期神经网络多输入单输出回归预测 目录 回归预测 | MATLAB实现BO-LSTM贝叶斯优化长短期神经网络多输入单输出回归预测效果一览基本介绍模型搭建程序设计参考资料 效果一览 基本介绍 MATLAB实现BO-LSTM贝叶斯优化长短期神经网络多输入…...
工厂干洗店洗鞋店系统,校园洗护小程序来了
洗鞋店小程序,干洗店软件,洗护行业小程序,上门取衣小程序,预约干洗小程序,校园干洗店小程序,工厂干洗店小程序,干洗店小程序开发,成品软件开发 洗衣工厂软件、功能强大! 包含以下主要功能: * 用户选择洗护用品&#x…...
计算机毕设 opencv 图像识别 指纹识别 - python
文章目录 0 前言1 课题背景2 效果展示3 具体实现3.1 图像对比过滤3.2 图像二值化3.3 图像侵蚀细化3.4 图像增强3.5 特征点检测 4 OpenCV5 最后 0 前言 🔥 这两年开始毕业设计和毕业答辩的要求和难度不断提升,传统的毕设题目缺少创新和亮点,往…...
简化通知基础设施:开源的消息通知服务 | 开源专题 No.41
novuhq/novu Stars: 22.9k License: MIT Novu 是一个开源的通知基础设施项目,它提供了统一的 API 来通过多个渠道发送通知,包括应用内、推送、电子邮件、短信和聊天。主要功能有: 为所有消息提供商 (应用内、电子邮件、短信、推送和聊天) 提…...
微信公众号排版写作
对话框添加菜单 05 一节课学会使用微信自动回复_哔哩哔哩_bilibili 一件扫图关注 一件扫描付款 公众号排版 10元付费 08 —长按二维码关注和收款_哔哩哔哩_bilibili 微信开店 09 一节课开设自己的微店_哔哩哔哩_bilibili 知乎软文,设置引流矩阵 20 —在知乎写…...
UE4/5 批量进行贴图Texture压缩、修改饱和度
该插件下载地址: 🍞正在为您运送作品详情https://mbd.pub/o/bread/ZZWYmpxw 适用于 UE4 4.25/4.26/4.27 UE5 以上版本 在Edit - Plugins中分别开启 插件 Python Editor Script Plugin 插件 Editor Scripting Utilites 如果会python代码,…...
mysql中limit和offset的用法详细介绍
有的时候我们在学习或者工作中会使用到SQL语句,那么介绍一下limit和offset的使用方法。 mysql里分页一般用limit来实现,例如: 1、select* from user limit 3 表示直接取前三条数据 2、select * from user limit 1,3; 表示取1后面的第2,3,…...
vivado简单仿真入门
打开软件 创建工程 create project 先next,保留工程路径,配置环境 配置芯片环境 本次芯片类型 xc7k325tffg900-2 创建之后完整的demo 编写仿真内容 timescale 1ns/1…...
Elsevier (爱思唯尔) 期刊 投稿流程与注意点
😄 Elsevier (爱思唯尔) 期刊投稿流程中还是遇到了不少问题的,本篇文章总结一些说明文档和提交要点。 ⭐ LaTex 模板说明 & 投稿流程与准备 latex模版和投稿流程相关参考说明可看下面几个网址,总结的非常全面了: Elsevier&am…...
centos Let‘s Encrypt 免费https证书申请,并且自动续约
一、首先我们要使用certbot 工具 官网地址: https://certbot.eff.org/instructions?wsother&oscentosrhel8 下载 snap 工具 sudo yum install snapd sudo systemctl enable --now snapd.socket sudo ln -s /var/lib/snapd/snap /snap sudo systemctl status…...
nodejs+vue城市轨道交通线路查询系统-计算机毕业设计
着社会的快速发展,计算机的影响是全面且深入的。社会生产水平的不断提高,日常生活中人们对备忘记账系统方面的要求也在不断提高,因特网的使用越来越广泛,而在众多的因特网中,万维网更是为人们带来了新鲜的体验。在这当…...
MFC Windows 程序设计[332]之十进制转十六进制编辑框(附源码)
MFC Windows 程序设计[332]之十进制转十六进制编辑框 程序之美前言主体运行效果核心代码逻辑分析结束语程序之美 前言 MFC是微软公司提供的一个类库(class libraries),以C++类的形式封装了Windows API,并且包含一个应用程序框架,以减少应用程序开发人员的工作量。其中包…...
转化率的催化剂:网站客服机器人如何推动企业销售?
随着5G的推广,人工智能技术的普及程度越来越高,人机交互已经成为这个时代的常态,无论是在我们的日常生活中还是在企业服务中都非常常见。如今,无论是营销型企业还是客服型企业,都纷纷采用网站客服机器人服务࿰…...
Go 包操作之如何拉取私有的Go Module
Go 包操作之如何拉取私有的Go Module 在前面,我们已经了解了GO 项目依赖包管理与Go Module常规操作,Go Module 构建模式已经成为了 Go 语言的依赖管理与构建的标准。 在平时使用Go Module 时候,可能会遇到以下问题: 在某 modul…...
VR酒店专业情景教学演示
VR酒店情景教学为学生带来的全新学习体验。在这个虚拟环境中,学生可以亲身经历各种酒店管理场景,从客房清洁、餐厅服务,到客人接待、突发事件处理,都能得到生动的模拟和实践。 客房清洁是酒店管理中最基础却也最重要的一环。通过V…...
odps函数
1、wm_concat 聚合函数,可以实现对分组后的列数据拼接成一行。 参数:第一个参数为分隔符,第二个参数为要聚合的列; select prov_code,wm_concat(-,city_name) from code_china_area group by prov_code; 2、datediff 日期函数…...
【golang】mysql默认排序无法实现 使用golang实现对时间字符串字段的排序
一、问题场景 1、mysql实现排序-性能低下 例如:某字段 finish_time 数据如下:6:13:27、 10:56:11、 21:56:11 会出现顺序如下的场景: 10:56:11、 21:56:11、6:13:27 二、解决方案 2、golang实现排序 package mainimport ("fmt"&…...
C语言学习笔记总结(一)
C语言基础 字节大小 char:1 字节 unsigned char:1 字节 short:2 字节 unsigned short:2 字节 int:通常为 4 字节(32 位平台)或 8 字节(64 位平台) unsigned int&#x…...
WPF:自定义按钮模板
1.WPF:自定义按钮模板 自定义封装的按钮属性可写在<Button.Template>中 Background"{TemplateBinding Background}"中的TemplateBinding代表使用按钮本身所使用的背景颜色 不在样式内修改背景颜色 例如: <Button Width"300" Height&q…...
(十)学生端搭建
本次旨在将之前的已完成的部分功能进行拼装到学生端,同时完善学生端的构建。本次工作主要包括: 1.学生端整体界面布局 2.模拟考场与部分个人画像流程的串联 3.整体学生端逻辑 一、学生端 在主界面可以选择自己的用户角色 选择学生则进入学生登录界面…...
黑马Mybatis
Mybatis 表现层:页面展示 业务层:逻辑处理 持久层:持久数据化保存 在这里插入图片描述 Mybatis快速入门 是一种强大的机制,允许程序在运行时访问和操作类的内部属性和方法。通过反射,可以动态地创建对象、调用方法、改变属性值,这在很多Java框架中如Spring和Hiberna…...
令牌桶 滑动窗口->限流 分布式信号量->限并发的原理 lua脚本分析介绍
文章目录 前言限流限制并发的实际理解限流令牌桶代码实现结果分析令牌桶lua的模拟实现原理总结: 滑动窗口代码实现结果分析lua脚本原理解析 限并发分布式信号量代码实现结果分析lua脚本实现原理 双注解去实现限流 并发结果分析: 实际业务去理解体会统一注…...
三体问题详解
从物理学角度,三体问题之所以不稳定,是因为三个天体在万有引力作用下相互作用,形成一个非线性耦合系统。我们可以从牛顿经典力学出发,列出具体的运动方程,并说明为何这个系统本质上是混沌的,无法得到一般解…...
SpringTask-03.入门案例
一.入门案例 启动类: package com.sky;import lombok.extern.slf4j.Slf4j; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cache.annotation.EnableCach…...
rnn判断string中第一次出现a的下标
# coding:utf8 import torch import torch.nn as nn import numpy as np import random import json""" 基于pytorch的网络编写 实现一个RNN网络完成多分类任务 判断字符 a 第一次出现在字符串中的位置 """class TorchModel(nn.Module):def __in…...
Aspose.PDF 限制绕过方案:Java 字节码技术实战分享(仅供学习)
Aspose.PDF 限制绕过方案:Java 字节码技术实战分享(仅供学习) 一、Aspose.PDF 简介二、说明(⚠️仅供学习与研究使用)三、技术流程总览四、准备工作1. 下载 Jar 包2. Maven 项目依赖配置 五、字节码修改实现代码&#…...
VM虚拟机网络配置(ubuntu24桥接模式):配置静态IP
编辑-虚拟网络编辑器-更改设置 选择桥接模式,然后找到相应的网卡(可以查看自己本机的网络连接) windows连接的网络点击查看属性 编辑虚拟机设置更改网络配置,选择刚才配置的桥接模式 静态ip设置: 我用的ubuntu24桌…...
面向无人机海岸带生态系统监测的语义分割基准数据集
描述:海岸带生态系统的监测是维护生态平衡和可持续发展的重要任务。语义分割技术在遥感影像中的应用为海岸带生态系统的精准监测提供了有效手段。然而,目前该领域仍面临一个挑战,即缺乏公开的专门面向海岸带生态系统的语义分割基准数据集。受…...

