架构师训练营 1 期 - 第五周作业 (vaik)
发布于: 2020 年 10 月 25 日
用你熟悉的编程语言实现一致性 hash 算法。
import java.util.*;
//基于虚拟节点的一致性哈希算法
public class DistributedConsistentHashingByVirtualNode {
//缓存服务器虚拟节点映射列表
private SortedMap<Integer,String> virtualCacheServerKeyList =new TreeMap<>();
//每台缓存服务器映射的虚拟节点数量,默认200
private int cacheServerMappingNumber = 200;
//构建类时提供可设置每台缓存服务器映射的虚拟节点数量
public DistributedConsistentHashingByVirtualNode(int cacheServerMappingNumber) {
this.cacheServerMappingNumber = cacheServerMappingNumber;
}
//添加缓存服务器
public void AddCacheServer(String serverIp){
for(int i=0;i<cacheServerMappingNumber;i++){
String nodeKey = i*10000+"_"+serverIp+"_"+i*10000;
int hashCode = nodeKey.hashCode();
virtualCacheServerKeyList.put(hashCode,serverIp);
}
}
//删除缓存服务器
public void RemoveCacheServer(String serverIp){
for(int i=0;i<cacheServerMappingNumber;i++){
String nodeKey = i*10000+"_"+serverIp+"_"+i*10000;
int hashCode = nodeKey.hashCode();
virtualCacheServerKeyList.remove(hashCode);
}
}
//根据缓存Key查找缓存所在的缓存服务器IP
public String getCacheServerIpByKey(String key){
int hashCode = key.hashCode();
String ip = "";
Iterator<Map.Entry<Integer,String>> entries = virtualCacheServerKeyList.entrySet().iterator();
while(entries.hasNext()){
Map.Entry<Integer, String> entry = entries.next();
int virtualCacheServerKey = entry.getKey();
ip = entry.getValue();
//判断顺时针与hashCode最接近的缓存服务器节点
if(hashCode<=virtualCacheServerKey){
break;
}
}
return ip;
}
//打印虚拟结点分布情况
public void printAllVirtualCacheServerKey(){
Iterator<Map.Entry<Integer,String>> entries = virtualCacheServerKeyList.entrySet().iterator();
while(entries.hasNext()){
Map.Entry<Integer, String> entry = entries.next();
int virtualCacheServerKey = entry.getKey();
String ip = entry.getValue();
System.out.println("virtualCacheServerKey:"+virtualCacheServerKey+" ip:"+ip);
}
}
}
复制代码
2.编写测试用例测试这个算法,测试 100 万 KV 数据,10 个服务器节点的情况下,计算这些 KV 数据在服务器上分布数量的标准差,以评估算法的存储负载不均衡性。
测试结果
import java.util.HashMap;
import java.util.Random;
public class TestDistributedConsistentHashingByVirtualNode {
public static void main(String[] args){
DistributedConsistentHashingByVirtualNode nodeServer = new DistributedConsistentHashingByVirtualNode(100);
String nodeServerIp1 = "192.168.1.1";
String nodeServerIp2 = "192.168.1.2";
String nodeServerIp3 = "192.168.1.3";
String nodeServerIp4 = "192.168.1.4";
String nodeServerIp5 = "192.168.1.5";
String nodeServerIp6 = "192.168.1.6";
String nodeServerIp7 = "192.168.1.7";
String nodeServerIp8 = "192.168.1.8";
String nodeServerIp9 = "192.168.1.9";
String nodeServerIp10 = "192.168.1.10";
nodeServer.AddCacheServer(nodeServerIp1);
nodeServer.AddCacheServer(nodeServerIp2);
nodeServer.AddCacheServer(nodeServerIp3);
nodeServer.AddCacheServer(nodeServerIp4);
nodeServer.AddCacheServer(nodeServerIp5);
nodeServer.AddCacheServer(nodeServerIp6);
nodeServer.AddCacheServer(nodeServerIp7);
nodeServer.AddCacheServer(nodeServerIp8);
nodeServer.AddCacheServer(nodeServerIp9);
nodeServer.AddCacheServer(nodeServerIp10);
//nodeServer.printAllVirtualCacheServerKey();
HashMap<String,Integer> result = new HashMap<>();
//测试100万随机Key(3到100位长度的Key)在 10个服务器上的分布比例
for (int i=0 ; i<1000000; i++){
Random random=new Random();
int number=random.nextInt(98)+3;
String key = getRandomString(number);
String nodeServerIp = nodeServer.getCacheServerIpByKey(key);
if(result.containsKey(nodeServerIp)){
result.put(nodeServerIp,result.get(nodeServerIp)+1);
}else{
result.put(nodeServerIp,1);
}
}
for (String key: result.keySet()) {
int num = result.get(key);
double rate = (double) num/1000000;
String rateStr = String.format("%.4f",rate*100);
System.out.println("ServerIP:"+key+" Key数量:"+num + " 占比:"+rateStr+"% ");
}
}
//取固定位数的随机字符串
public static String getRandomString(int length){
String str="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
Random random=new Random();
StringBuffer sb=new StringBuffer();
for(int i=0;i<length;i++){
int number=random.nextInt(62);
sb.append(str.charAt(number));
}
return sb.toString();
}
}
复制代码
划线
评论
复制
发布于: 2020 年 10 月 25 日阅读数: 35
行之
关注
还未添加个人签名 2018.09.18 加入
还未添加个人简介
评论