第五周命题作业
发布于: 2020 年 12 月 26 日
1. 用你熟悉的编程语言实现一致性 hash 算法。
1)逻辑图如下:
2)JAVA语言实现如下:
定义正式缓存虚拟机类:
package gaoyong.jaigou.sf;//负载均衡的机器节点信息,name,ip,port,numCachepublic 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(); } }}
对应的折线图:
划线
评论
复制
发布于: 2020 年 12 月 26 日阅读数: 13
cc
关注
还未添加个人签名 2018.03.19 加入
还未添加个人简介
评论