import org.apache.commons.lang3.RandomUtils;
import org.apache.commons.lang3.StringUtils; import java.util.*; /**
* 一致性hash
*/
public class ConsistentHashWithVirtualNode { /**
* 待添加入Hash环的服务器列表
*/ private static String[] SERVERS = {"192.168.1.2:6379", "192.168.1.3:6379"}; /**
* key表示服务器的hash值,value表示虚拟节点的名称
*/
private static SortedMap<Integer, String> HASH_CIRCLE = new TreeMap<Integer, String>();
/**
* 用于结果统计
*/
private static Map<String, Integer> result = new HashMap<String, Integer>();
/**
* 每个真实节点对应虚拟节点数
*/
private static Integer VIRTUAL_NODES_NUM = 150; /**
* 使用FNV1_32_HASH算法计算服务器的Hash值
*/
private static int getHash(String str) {
final int p = 16777619;
int hash = (int) 2166136261L;
for (int i = 0; i < str.length(); i++)
hash = (hash ^ str.charAt(i)) * p;
hash += hash << 13;
hash ^= hash >> 7;
hash += hash << 3;
hash ^= hash >> 17;
hash += hash << 5; // 如果值为负数则取其绝对值
if (hash < 0)
hash = Math.abs(hash);
return hash;
} static {
for (int i = 0; i < SERVERS.length; i++) {
for (Integer j = 0; j < VIRTUAL_NODES_NUM; j++) {
setServer(SERVERS[i] + "vn" + j);
}
}
} private static void setServer(String ip) {
setServer(ip, null);
} private static void setServer(String ip, Integer hash) {
hash = hash != null ? getHash(hash.toString()) : getHash(ip);
if (StringUtils.isBlank(HASH_CIRCLE.get(hash))) {
HASH_CIRCLE.put(hash, ip);
System.out.println("[" + ip + "]加入sortedMap中, 其Hash值为" + hash);
} else {
//解决hash碰撞
setServer(ip, hash);
}
} public static void main(String[] args) {
for (int i = 0; i < 50; i++) {
long nodes = RandomUtils.nextLong();
String server = getServer(nodes);
String realServer = server.split("vn")[0];
System.out.println("[" + nodes + "]的hash值为" + getHash("" + nodes) + ", 被路由到虚拟结点[" + server + "], 真实结点[" + realServer + "]");
result.put(realServer, (result.get(realServer) == null ? 0 : result.get(realServer)) + 1);
}
result.forEach((k, v) -> {
System.out.println("结点[" + k + "]上有" + v);
});
} public static String getServer(Object node) {
String ip = HASH_CIRCLE.get(HASH_CIRCLE.firstKey());
// 得到带路由的结点的Hash值
int hash = getHash(node.toString());
// 得到大于该Hash值的所有Map
SortedMap<Integer, String> subMap = HASH_CIRCLE.tailMap(hash); if (!subMap.isEmpty()) {
// 第一个Key就是顺时针过去离node最近的那个结点
Integer i = subMap.firstKey();
ip = subMap.get(i);
}
// 返回对应的服务器名称
return ip;
}
}

java实现hash一致性算法的更多相关文章

  1. 【java】安全加密MessageDigest的功能及用法【hash一致性算法】

    链接地址:https://blog.csdn.net/ma1kong/article/details/2662997 1.查看MessageDigest源码的注释说明 2.和hash一致性算法 什么关 ...

  2. 【hash】什么是hash,什么是哈希,什么是hash散列,什么是hash一致性算法【关于hash的详解】

    什么是hash,什么是哈希,什么是hash散列,什么是hash一致性算法

  3. hash一致性算法

    一致性hash算法是,1097麻省理工提出的分布式hashDHT实现算法,极倔internet的热点问题 平衡性 hash结果尽可能的分布到所有的缓存中去,缓冲空间利用率最高 单调性 保持已有的缓存能 ...

  4. 【Hash一致性算法】什么是Hash一致性算法

    目录 1. 一致性Hash算法简介 环形Hash空间 把数据通过一定的hash算法处理后映射到环上 将机器通过hash算法映射到环上 机器的删除与添加 平衡性 本文转载自博客 1. 一致性Hash算法 ...

  5. Hash一致性算法底层原理

    大纲 Hash取余算法 判定哈希算法好坏的四个定义 一致性Hash算法的两大设计 Hash取余算法 hash(Object.key)%N,hash值随Object.key.N的变化而变化. 如果有节点 ...

  6. 【java】hash一致性算法的实现区别【标题暂定】

    下面两个都是在生成sign签名时候用到的方式,有什么区别? 第一种: import org.apache.commons.codec.digest.DigestUtils; String sign = ...

  7. redis 集群引出hash一致性算法

    写的很棒的文章 https://blog.csdn.net/bntX2jSQfEHy7/article/details/79549368 这篇分析的更叼 https://www.jianshu.com ...

  8. nginx+php+memcache实现hash一致性memcache 集群

    我们工作中可能会遇到key-value数据库,如果我们面对的不止一台memcache服务器,而是很多台.那么现在就回出现一个问题: 当我们访问nginx服务器的时候,我们会判断memcache中是否有 ...

  9. 11.redis cluster的hash slot算法和一致性 hash 算法、普通hash算法的介绍

    分布式寻址算法 hash 算法(大量缓存重建) 一致性 hash 算法(自动缓存迁移)+ 虚拟节点(自动负载均衡) redis cluster 的 hash slot 算法 一.hash 算法 来了一 ...

随机推荐

  1. 人脸检测——MTCNN

    人脸检测——MTCNN .

  2. const限定符用法汇总

    const限定符限定变量的类型是一个常量,对象一旦创建后其值就无法改变,所以const对象必须初始化. 初始化 const int i = get_size(); //运行时初始化 const int ...

  3. 05- views视图层

    1.配置index 主url from django.contrib import admin from django.urls import path, re_path, include urlpa ...

  4. spark遇到的一些问题及其解决办法

    1.报错:ERROR storage.DiskBlockObjectWriter: Uncaught exception while reverting partial writes to file ...

  5. iOS开发-通过正则表达式判断字符串是否为纯阿拉伯数字

    iOS开发-通过正则表达式判断字符串是否为纯阿拉伯数字 简述:NSString * regex_0 = @"\\d{1,}";   /*允许首位为0*/ NSString * re ...

  6. P3871 [TJOI2010]中位数

    傻逼题 维护两个系统堆即可 #include<bits/stdc++.h> #define il inline #define vd void typedef long long ll; ...

  7. docker-compose 部署 EFK

    信息: Docker版本($ docker --version):Docker版本18.06.1-ce,版本e68fc7a 系统信息($ cat /etc/centos-release):CentOS ...

  8. mysql查询当天,前一天,一周,一个月

    当天 select * from 表名 where to_days(时间字段名) = to_days(now()); 昨天 SELECT * FROM 表名 WHERE TO_DAYS( NOW( ) ...

  9. 解决了一个困扰我近一年的vim显示中文乱码的问题

    今天解决了vi命令打开日志文件中文总是显示乱码的问题.由于项目组中的日志包含一些特殊字符,所以使用vim打开日志文件时总是不能正确识别出文件字符编码.此时用:set fileencoding命令可以看 ...

  10. TPO-23 C2 Advice on choosing courses

    第 1 段 1.Listen to a conversation between a student and his English professor. 请听一段学生与他的英文教授的对话. 第 2 ...