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

【分布式存储】聊聊一致性哈希算法原理和实现

负载均衡问题

在实际的生产环境中,一般都是提供多个服务进行处理,比如对于用户中心提供多个节点,那么上游系统如何保证获取其中一个节点进行进行处理呢,这就是负载均衡问题。而在服务治理中,dubbo有几种策略。主流的就是加权轮训方式。
在这里插入图片描述

但是有一种场景 那就是如果每个节点都保存有状态的数据,我们只想某个用户固定访问固定的机器。你怎么解决, 其实使用hash算法就可以解决, 比如通过用户uid%节点个数 每次访问可以到固定节点节点。虽然这样可以解决,但是在针对节点数量变化的时候,mode就需要变化,这样通常可能导致整体节点重新计算。 所以就引入一致性哈希算法。

原理

他其实就是划分成2^32次方的空间,通过部署不同的节点,然后按照客户端计算的hash,统一的往顺时针找到最近的一个节点进行请求处理。
在这里插入图片描述
这样可以避免的问题是什么:就是当一个节点C出现故障 或者 人工下线时,影响的面只有一部分。
但是在极端情况下 可能出现数据节点倾斜的问题。如何解决呢?

其实就是虚拟一致性哈希算法。
在这里插入图片描述
通过增加多个虚拟节点,可以均匀的多个承担处理请求。即使某个节点出现故障,影响的范围也小。

code

/**** @author qxlx* @date 2025/7/27 09:43*/
public class ConsistentHash {// 虚拟1024个节点private static final int VIRTUAL_NODE_NUM = 1024;private static final int REAL_NODE_NUM = 10;private Map<Integer,String> realServiceNodes;private Map<Integer,String> virtualServiceNodes;public ConsistentHash() {init();}private void init() {realServiceNodes = new ConcurrentHashMap<>(REAL_NODE_NUM);virtualServiceNodes = new ConcurrentHashMap<>(VIRTUAL_NODE_NUM);// 初始化真实节点for (int i = 0; i < REAL_NODE_NUM; i++) {realServiceNodes.put(i,"192.168.0."+i);}// 初始化虚拟节点for (int i = 0; i < VIRTUAL_NODE_NUM; i++) {virtualServiceNodes.put(i,realServiceNodes.get(i % REAL_NODE_NUM));}}// 根据虚拟节点 查找真实节点public String getRealNodeServer(String key) {// 计算在虚拟节点的位置int index = key.hashCode() % VIRTUAL_NODE_NUM;// 根据虚拟节点 找到真实节点String node = virtualServiceNodes.get(index);if (node == null) {throw new IllegalArgumentException("没有找到对应的服务节点");}return node;}// 删除一个真实节点public void removeRealNode(String realNode) {if (realNode == null) {return;}for (Map.Entry<Integer,String> entry : realServiceNodes.entrySet()) {if (entry.getValue().equals(realNode)) {realServiceNodes.remove(entry.getKey());}}for (Map.Entry<Integer,String> entry : virtualServiceNodes.entrySet()) {if (entry.getValue().equals(realNode)) {virtualServiceNodes.remove(entry.getKey());}}}public static void main(String[] args) {ConsistentHash consistentHash = new ConsistentHash();String realNodeServer = consistentHash.getRealNodeServer("1");System.out.println("realNodeServer:"+realNodeServer);consistentHash.removeRealNode("192.168.0.1");}
}

参考

https://www.cnblogs.com/binyue/p/17344216.html

http://www.dtcms.com/a/301751.html

相关文章:

  • Linux图片元数据提取完全指南:从基础到高级的完整教程
  • day25
  • EPOLLONESHOT 深度解析:Linux epoll 的单次触发机制
  • 单表查询-or优化
  • SpringIoCDI
  • Java 集合进阶:从 Collection 接口到迭代器的实战指南
  • AI入门学习-模型评估示例讲解
  • 解决浏览器无法删除cookie的问题
  • JavaSE知识点(2)
  • mybatis的insert(pojo),会返回pojo吗
  • 2507C++,APC可以干的活
  • Leetcode 3628. Maximum Number of Subsequences After One Inserting
  • mybatis-plus逻辑删除配置
  • 高可用集群KEEPALIVED实战解析
  • Gradio全解8——ChatInterfaceChatbot:聊天界面类与聊天机器人(2)——ChatInterface的自定义函数和界面
  • 芯片库和标准库寻找的方法
  • print(“\033[31m红\033[32m绿\033[34m蓝\033[0m默认色“)
  • 随机密码生成
  • Spring IOC 容器 **默认注册 Bean** 的 8 条规则
  • 网络服务综合项目
  • 数据结构基础内容(第七篇:堆、哈夫曼树)
  • SABR-Net
  • Linux 系统文件夹结构及用途说明
  • 《频率之光:共振之战》
  • 题解:CF1010C Border
  • Python异常处理:金融风控系统中的救命盾牌
  • Web开发系列-第13章 Vue3 + ElementPlus
  • 第十二讲:C++继承
  • 每日算法刷题Day55:7.27:leetcode 复习完第K小/大+栈4道题,用时1h50min
  • Datawhale 科大讯飞AI大赛(模型蒸馏)