架构师训练营作业 (第五周)
发布于: 2020 年 07 月 08 日
作业一:
- 用你熟悉的编程语言实现一致性 hash 算法。 
- 编写测试用例测试这个算法,测试 100 万 KV 数据,10 个服务器节点的情况下,计算这些 KV 数据在服务器上分布数量的标准差,以评估算法的存储负载不均衡性。 
package com.hash;/** * hash 算法 * @create 2020-07-08 20:43 */public class CustomHashUtil {    public static int hashCode(String key) {        final int p = 16776619;        int hash = (int) 2166136261L;        for(int i = 0; i < key.length(); i++) {            hash = (hash ^ key.charAt(i)) * p;        }        hash += hash << 13;        hash ^= hash >> 7;        hash += hash << 3;        hash ^= hash >> 17;        hash += hash << 5;        hash = Math.abs(hash);        return hash;    }}package com.hash;import java.util.HashMap;import java.util.Map;/** * @create 2020-07-08 21:00 */public class Node {    private String domain;    private int count = 0;    private Map<String, Object> data = new HashMap();    public Node(String domain) {        this.domain= domain;    }    public <T> void put(String key,String value) {        data.put(key,value);        count++;    }    public void remove(String key){        data.remove(key);        count--;    }    public <T> T get(String key) {        return (T) data.get(key);    }    public int getCount() {        return count;    }    public String getName() {        return domain;    }}package com.hash;import java.util.LinkedList;import java.util.SortedMap;import java.util.TreeMap;/** * @create 2020-07-08 21:03 */public class CustomServer {    //待添加入Hash环的真实服务器节点列表    private  LinkedList<Node> realNodes = new LinkedList<>();    //虚拟节点列表    private  SortedMap<Integer, Node> sortedMap = new TreeMap<Integer, Node>();    public CustomServer() {        init();    }    private void init() {        //初始化服务器数量        for (int i = 0; i < 10; i++) {            String nodeName = "server"+i;            Node node = new Node(nodeName);            realNodes.add(node);        }        //引入虚拟节点: 添加1000倍虚拟节点,将10台server对应的虚拟节点放入TreeMap中        for (Node node : realNodes) {            for (int i = 1; i <=1000; i++) {                String nodeName = node.getName() + "-VM" + String.valueOf(i);                int hash = CustomHashUtil.hashCode(nodeName);                sortedMap.put(hash, node);            }        }    }    //得到应当路由到的结点    protected   Node getNode(String key) {        //得到该key的hash值        int hash = CustomHashUtil.hashCode(key);        //得到大于该Hash值的所有Map        Node node;        SortedMap<Integer, Node> subMap = sortedMap.tailMap(hash);        if (subMap.isEmpty()) {            //如果没有比该key的hash值大的,则从第一个node开始            Integer i = sortedMap.firstKey();            //返回对应的服务器            node = sortedMap.get(i);        } else {            //第一个Key就是顺时针过去离node最近的那个结点            Integer i = subMap.firstKey();            //返回对应的服务器            node= subMap.get(i);        }        if(node!=null) {            node.put(key,hash+"");            System.out.println(node.getName());        }        return node;    }    //获取实际服务器上负载平均值    private   double getAverage(LinkedList<Node> arr) {        double sum = 0;        int number = arr.size();        for (int i = 0; i < number; i++) {            Node node =arr.get(i);            sum += node.getCount();        }        return sum / number;    }    //获取实际服务器上负载的标准差    protected   double getStandardDevition(LinkedList<Node> arr) {        double sum = 0;        int number = arr.size();        double avgValue = getAverage(arr);//获取平均值        for (int i = 0; i < number; i++) {            Node node =arr.get(i);            sum += Math.pow((node.getCount() - avgValue), 2);        }        return Math.sqrt((sum / (number - 1)));    }    public LinkedList<Node> getRealNodes() {        return realNodes;    }    public SortedMap<Integer, Node> getSortedMap() {        return sortedMap;    }}package com.hash;import lombok.extern.slf4j.Slf4j;/** * @create 2020-07-08 21:09 */@Slf4jpublic class Test {    public static void main(String[] args) {        CustomServer customServer=new CustomServer();        //模拟节点        for (int i = 0; i < 1000000; i++) {            String key = "用户:"+i;            System.out.println(key + "的hash值为" + CustomHashUtil.hashCode(key) + ", 对应结点:" + customServer.getNode(key).getName() + "");        }        //打印 Node的实际负载        for (int i = 0; i < customServer.getRealNodes().size(); i++) {            Node node = customServer.getRealNodes().get(i);            System.out.println("服务器:" + node.getName()+",对应用户数量:"+node.getCount());        }        System.out.println("标准差:"+customServer.getStandardDevition(customServer.getRealNodes())+"");    }}
划线
评论
复制
发布于: 2020 年 07 月 08 日阅读数: 43
小遵
关注
还未添加个人签名 2018.06.16 加入
还未添加个人简介











 
    
评论