理解一致性hash算法以及TreeMap简易实现示例
SegmentFault
共 3866字,需浏览 8分钟
· 2020-08-19
作者:niewj
来源:SegmentFault 思否
1. 算法说明
目的: 一致性hash算法的目的, 就是为了解决2个问题:
hash算法中损毁节点对应的请求失败; 有节点损毁后, 请求落点不均匀问题;
2. 示例说明
一个hash环, 模拟节点数为1024个, 实际可用的节点有8个(比如线上实际的ip服务节点), 1024个模拟节点跟8个ip节点有均匀的映射关系;
我们模拟的环上有 1024 个虚拟节点, 真实可用的节点(可以想象为线上实际集群有8个可用ip供存储)
使用一致性hash使用方法:
环上的虚拟节点跟所有真实节点之间有个映射关系 (1024个节点跟8个节点的映射, 用的是除8取模的对应关系,
例如: 0, 8, 16, 24 都对应到node_0;
1, 7, 15, 23都映射到node_1);发一个请求字符串, 我们计算出hash值, 除 1024 取模; 将取模结果, 先映射到虚拟节点环上的点, 比如 "hello"的hashcode/1024 = 210 查询虚拟环和真实节点映射关系, 210对应的真实节点为 node_2; 于是, "hello" 就落到节点 node_2 上; 我们可以调用 com.niewj.dsalg.ConsistentHashMock#dropBadNode("node_2") 来删除 node_2节点; 删除 node_2 后, "hello"应该落在 211 上, 对应到环的真实映射, 是 node_3 , 于是, "hello"的请求就落到 node_3;
这, 就是 一致性hash算法!
3. 算法代码示例:
package com.niewj.dsalg;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;
/**
* Created by niewj on 2020/8/14 18:40
*/
public class ConsistentHashMock {
/**
* 假设我们一共初始化有8个节点(可以是ip, 就理解为ip吧);
* 把 1024个虚拟节点跟 8个资源节点相对应
*/
public static Map
realNodeMap = new HashMap<>(); public static int V_NODES = 1024; // 假设我们的环上有1024个虚拟节点
static TreeMap
virtualNodeMap = new TreeMap<>(); private static final Integer REAL_NODE_COUNT = 8;
static {
realNodeMap.put(0, "node_0");
realNodeMap.put(1, "node_1");
realNodeMap.put(2, "node_2");
realNodeMap.put(3, "node_3");
realNodeMap.put(4, "node_4");
realNodeMap.put(5, "node_5");
realNodeMap.put(6, "node_6");
realNodeMap.put(7, "node_7");
for (Integer i = 0; i < V_NODES; i++) {
// 每个虚拟节点跟其取模的余数的 nodeMap 中的key相对应;
// 下面删除虚拟节点的时候, 就可以根据取模规则来删除 TreeMap中的节点了;
virtualNodeMap.put(i, realNodeMap.get(i % REAL_NODE_COUNT));
}
}
/**
* 输入一个id
*
* @param value
* @return
*/
public static String getRealServerNode(String value) {
// 1. 传递来一个字符串, 得到它的hash值
Integer vnode = value.hashCode() % 1024;
// 2.找到对应节点最近的key的节点值
String realNode = virtualNodeMap.ceilingEntry(vnode).getValue();
return realNode;
}
/**
* 模拟删掉一个物理可用资源节点, 其他资源可以返回其他节点
*
* @param nodeName
*/
public static void dropBadNode(String nodeName) {
int nodek = -1;
// 1. 遍历 nodeMap 找到故障节点 nodeName对应的key;
for (Map.Entry
entry : realNodeMap.entrySet()) { if (nodeName.equalsIgnoreCase(entry.getValue())) {
nodek = entry.getKey();
break;
}
}
if (nodek == -1) {
System.err.println(nodeName + "在真实资源节点中无法找到, 放弃删除虚拟节点!");
return;
}
// 2. 根据故障节点的 key, 对应删除所有 chMap中的虚拟节点
Iterator
> iter = virtualNodeMap.entrySet().iterator(); while (iter.hasNext()) {
Map.Entry
entry = iter.next(); int key = entry.getKey();
String value = entry.getValue();
if (key % REAL_NODE_COUNT == nodek) {
System.out.println("删除节点虚拟节点: [" + key + " = " + value + "]");
iter.remove();
}
}
}
public static void main(String[] args) {
// 1. 一个字符串请求(比如请求字符串存储到8个节点中的某个实际节点);
String requestValue = "hello";
// 2. 打印虚拟节点和真实节点的对应关系;
System.out.println(virtualNodeMap);
// 3. 核心: 传入请求信息, 返回实际调用的节点信息
System.out.println(getRealServerNode(requestValue));
// 4. 删除某个虚拟节点后
System.out.println("==========删除 node_2 之后: ================");
dropBadNode("node_2");
System.out.println("===============删除之后的虚拟节点map: ===========");
System.out.println(virtualNodeMap);
System.out.println("==============删除之后, 获取节点的真正node节点对应者: ");
System.out.println(getRealServerNode(requestValue));
}
}
评论
特征提取:传统算法 vs 深度学习
点击上方“小白学视觉”,选择加"星标"或“置顶”重磅干货,第一时间送达编者荐语 特征提取是计算机视觉中的一个重要主题。不论是SLAM、SFM、三维重建等重要应用的底层都是建立在特征点跨图像可靠地提取和匹配之上。特征提取是计算机视觉领域经久不衰的研究热点,总的来说,快速、准确、鲁棒的特征点提
小白学视觉
0
三个优秀的PyTorch实现语义分割框架
点击上方“小白学视觉”,选择加"星标"或“置顶”重磅干货,第一时间送达转自 | 机器学习AI算法工程使用的VOC数据集链接开放在文章中,预训练模型已上传Github,环境我使用Colab pro,大家下载模型做预测即可。代码链接: https://github.com/lixiang007
小白学视觉
0
15种时间序列预测方法总结(包含多种方法代码实现)
向AI转型的程序员都关注了这个号👇👇👇在这篇文章中,我们将深入探讨时间序列预测的基本概念和方法。我们将首先介绍单元预测和多元预测的概念,然后详细介绍各种深度学习和传统机器学习方法如何应用于时间序列预测,包括循环神经网络(RNN)、一维卷积神经网络(1D-CNN)、Transformer、自回归模型(
机器学习AI算法工程
0
架构应该如何来理解?
来源:zhuanlan.zhihu.com/p/141027477👉 欢迎加入小哈的星球 ,你将获得: 专属的项目实战 / Java 学习路线 / 一对一提问 / 学习打卡 / 赠书福利全栈前后端分离博客项目 2.0 版本完结啦, 演示链接:htt
小哈学Java
0
SpringBoot 实现图片防盗链功能
程序员的成长之路互联网/程序员/技术/资料共享 关注阅读本文大概需要 4 分钟。来自:blog.csdn.net/weixin_46157208/article/details/138051737前言出于安全考虑,我们需要后端返回的图片只允许在某个网站内展示,不想被爬虫拿到图片地
程序员的成长之路
0
一站式解决方案:基于 Arthas 实现服务发现和权限控制
来源:juejin.cn/post/7281849496983994383👉 欢迎加入小哈的星球 ,你将获得: 专属的项目实战 / Java 学习路线 / 一对一提问 / 学习打卡 / 赠书福利全栈前后端分离博客项目 2.0 版本完结啦, 演示链接
小哈学Java
0
用 Shader 实现旗帜飘扬动画效果
我觉得对于刚入门 3D 编程的朋友来说,如果能够完成代码创建模型数据->创建材质->编写Shader动画这一系列,想必会有满满的成就感。今天就用 Cocos Creator 的 utils.MeshUtils.createMesh 接口,带大家感受一下这个流程。这个流程不仅可以用于新手学
COCOS
2
你真的理解 devDependencies 和 dependencies 的区别吗?
点击上方 前端Q,关注公众号回复加群,加入前端Q技术交流群作者:井柏然原文:https://juejin.cn/post/7135795969370619918你是否真的理解 devDependencies 和 dependencies 的区别?如果不能确切的回答、理解还停留在模糊的阶段,
前端Q
0