架构师训练营 -- 第五周作业
发布于: 2020 年 07 月 05 日
用你熟悉的编程语言实现一致性hash算法
import java.util.*;import java.util.concurrent.ThreadLocalRandom;public class HashConsistent { /** 服务器列表,也可以从配置中读取相关配置 */ private static String[] servers = {"192.168.1.1:12", "192.168.1.2:12", "192.168.1.3:12", "192.168.1.4:12", "192.168.1.5:12", "192.168.1.6:12", "192.168.1.7:12", "192.168.1.8:12", "192.168.1.9:12", "192.168.1.10:12"}; /** 真实的server节点信息 */ private static List<String> realNodes = new LinkedList<String>(); private static SortedMap<Integer, String> map = new TreeMap<>(); /** 虚拟节点数量 也可以从配置中读取相关配置 */ private static final int VIRTUAL_NODE_SIZE = 50; static { for (String server : servers) { realNodes.add(server); } for (String realNode : realNodes) { for (int i = 0; i < VIRTUAL_NODE_SIZE; i++) { String virtualNodeName = realNode + "&&VN" + i; int hash = calculateHash(virtualNodeName); map.put(hash, virtualNodeName); } } } public HashConsistent() {} private static int calculateHash(String calStr) { final int p = 16777619; int hash = (int) 2166136261L; for (int i = 0; i < calStr.length(); i++) { hash = (hash ^ calStr.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; } private static String getServer(String node) { /** 得到带路由的结点的Hash值 */ int hash = calculateHash(node); /** 得到大于该Hash值的所有Map */ SortedMap<Integer, String> subMap = map.tailMap(hash); /** 第一个Key就是顺时针过去离node最近的那个结点 */ String virtualNode = subMap.get(subMap.firstKey()); return virtualNode.substring(0, virtualNode.indexOf("&&")); } public static void main(String[] args) { Map<String, Integer> summary = new HashMap<>(); int keySize = 1000000; ThreadLocalRandom random = ThreadLocalRandom.current(); for (int i = 0; i < keySize; i++) { try { int value = random.nextInt(keySize); String server = getServer(String.valueOf(value)); if(summary.containsKey(server)){ summary.put(server, summary.get(server) + 1); }else{ summary.put(server, 0); } }catch (Exception e){ } } Iterator<Map.Entry<String, Integer>> iterator = summary.entrySet().iterator(); while (iterator.hasNext()){ Map.Entry<String, Integer> entry = iterator.next(); System.out.println("server为"+ entry.getKey() + "分布了" + entry.getValue() +"个数据"); } }}
测试100万的数据,计算分布标准差,评估算法的负载均衡
执行结果如下所示:
server为192.168.1.10:12分布了72082个数据
server为192.168.1.3:12分布了97910个数据
server为192.168.1.2:12分布了80322个数据
server为192.168.1.1:12分布了109742个数据
server为192.168.1.4:12分布了124837个数据
server为192.168.1.5:12分布了92508个数据
server为192.168.1.8:12分布了92479个数据
server为192.168.1.9:12分布了89076个数据
server为192.168.1.7:12分布了124028个数据
server为192.168.1.6:12分布了116636个数据
目前来看负载均衡算法设置的数据分布还算均匀
划线
评论
复制
发布于: 2020 年 07 月 05 日 阅读数: 41
花花大脸猫
关注
小小老鼠小小老鼠不偷米大脸猫大脸猫爱吃鱼 2018.05.03 加入
一个默默无闻的码农大叔。。。。
评论