写点什么

第五周命题作业

用户头像
cc
关注
发布于: 2020 年 12 月 26 日

1. 用你熟悉的编程语言实现一致性 hash 算法。

1)逻辑图如下:

2)JAVA语言实现如下:

定义正式缓存虚拟机类:

package gaoyong.jaigou.sf;
//负载均衡的机器节点信息,name,ip,port,numCache
public class CacheNode {
private String name; //机器名称
private String ip; //机器IP
private String port; //机器端口
private int numCache; //缓存实体数量
public CacheNode(String name, String ip, String port) {
this.name = name;
this.ip = ip;
this.port = port;
this.numCache = 0;
}
public int addNumcache(){
return numCache++;
}
public int getNumCache() {
return numCache;
}
}



定义虚拟缓存机映射虚拟节点类,主要提供两个方法:

2.1 init()初始化hash环,建立虚拟节点和缓存服务器映射关系,为treemap结构

2.2 getShard(String key) 根据传入的key值,一般为hash值,顺时针找到最近一个虚拟节点,并且返回虚拟节点对应真实的虚拟机

package gaoyong.jaigou.sf;
import gaoyong.jaigou.sf.tool.HashTool;
import java.util.List;
import java.util.SortedMap;
import java.util.TreeMap;
//机器与虚拟机对应的类
public class Shard<T> {
private TreeMap<Integer,T> virNodes; //映射到hash的一组虚拟节点
private List<T> shards; //真实机器节点列表
private int virNodeNumer; //每个机器关联的虚拟节点数
public Shard(List<T> shards, int virNodeNumer) {
this.shards = shards;
this.virNodeNumer = virNodeNumer;
init();
}
/**
* 初始化一致性hash环
*/
private void init(){
virNodes = new TreeMap<Integer,T>();
for(int i =0;i<shards.size();i++){
T shard = shards.get(i);
for (int n =0;n<=virNodeNumer;n++){
virNodes.put(HashTool.hash("SHARD-"+i+"--NODE--")+n,shard);
}
}
}
/**
* 根据key值,得到真实的虚拟机
* @param key
* @return
*/
public T getShard(String key){
SortedMap<Integer,T> tail = virNodes.tailMap(HashTool.hash(key));//沿环的顺时针找到一个虚拟节点
if(tail.size()==0){
return virNodes.get(virNodes.firstKey());
}
return tail.get(tail.firstKey()); //返回该虚拟节点对应的真实机器节点信息
}
}

2. 编写测试用例测试这个算法,测试 100万KV 数据,10个服务器节点的情况下,计算 这些 KV 数据在服务器上分布数量的标准差,以评估算法的存储负载不均衡性。

写一 个测试类,主要完成以下功能:

1.初始化10台真实缓存虚拟机,返回到List集合

2.初始化Shard<T>类,返回真实缓存虚拟机对应的虚拟节点

3.初始化100KV数据,计算10台缓存虚拟机每台机器缓存对象的个数

4.虚拟节点每次循环步长20递增,直至500,计算标准差



代码如下:

package gaoyong.jaigou.sf;
import java.util.ArrayList;
import java.util.List;
public class HashTest {
public static void main(String[] args) {
final int NUM_CHACHENODE=10; //虚拟机节点
String name; //机器名称
String ip; //机器IP
String port ="8888"; //机器端口
for(int virNodeNum=0;virNodeNum<=500;virNodeNum=virNodeNum+20){ //virNodeNum 需要虚拟在环上的节点数量
//初始化机器节点
List<CacheNode> cacheNodes = new ArrayList<CacheNode>();
for (int i=0;i<=NUM_CHACHENODE;i++){
name=String.format("HashCache_.%d",i);
ip=String.format("192.168.10.%d",i);
CacheNode cacheNode = new CacheNode(name,ip,port);
cacheNodes.add(cacheNode);
}
long startTime=System.currentTimeMillis(); //程序开始执行时间
//初始化一致性hash环
Shard<CacheNode> virCacheNodes = new Shard<CacheNode>(cacheNodes,virNodeNum);
//初始化100万KV测试数据
for(int n = 0;n<=1000000;n++){
String key = String.format("%f",Math.random());
//System.out.println("随机生成测试数据,编号:"+n+",数据值:"+key);
CacheNode keyHash = virCacheNodes.getShard(key);
//对应机器node缓存数加1
keyHash.addNumcache();
}
long endTime=System.currentTimeMillis(); //程序开始执行时间
//平均值10w计算标准差
double std=0;
double avg =100000;
for (int i =0;i<NUM_CHACHENODE;i++){
CacheNode node =cacheNodes.get(i);
//System.out.println(" 每台机器node节点:" + i +" 缓存个数: " + (node.getNumCache()) );
std = std + Math.abs(avg - (double) node.getNumCache()) * Math.abs(avg - (double) node.getNumCache());
}
std = std/NUM_CHACHENODE;
std = Math.sqrt(std);
System.out.println("虚拟节点:"+virNodeNum+" 标准差: "+std);
System.out.println("虚拟节点:"+virNodeNum+" 100万次算法程序运行时间: "+(endTime-startTime) +"ms");
cacheNodes.clear();
}
}
}



对应的折线图:



用户头像

cc

关注

还未添加个人签名 2018.03.19 加入

还未添加个人简介

评论

发布
暂无评论
第五周命题作业