架构师训练营第 5 周课后作业
发布于: 2020 年 07 月 09 日
用你熟悉的编程语言实现一致性 hash 算法。
编写测试用例测试这个算法,测试 100 万 KV 数据,10 个服务器节点的情况下,计算这些 KV 数据在服务器上分布数量的标准差,以评估算法的存储负载不均衡性。
1.使用murmurhash 做hash函数,哈希冲突较低2.将服务器节点名称使用hash函数计算出hash值,放到hash环中。具体实现使用java的treemap,key是hash值,value 是节点.3.kv存放到节点,寻找节点逻辑。先将k使用hash函数计算出hash值,在treemap中找到比该hash值大的最小的节点,如果没有使用第一个节点4.10个节点kv数据分布不大均匀,可以给每个节点增加虚拟节点 public static void main(String[] args) { TreeMap<Long, String> circular = new TreeMap<>(); for (int i = 1; i <= 10; i++) { String node = "node" + i; circular.put(hash(node), node); } Map<String, Long> dataNodeCount = new TreeMap<>(); String dataKVPrefix = "dataKVPrefix"; for (int i = 0; i < 1000000; i++) { String key = dataKVPrefix + new Random().nextInt(); Map.Entry<Long, String> entry = circular.ceilingEntry(hash(key)); //找不到节点,找最小的 if (entry == null) { entry = circular.firstEntry(); } String node = entry.getValue(); Long count = dataNodeCount.get(node); count = count == null ? 1L : count + 1; dataNodeCount.put(node, count); } dataNodeCount.forEach((k, v) -> { System.err.println("node:" + k + ",data count:" + v); }); //标准差。sqrt(((x1-x)^2 +(x2-x)^2 +......(xn-x)^2)/n) int x = 1000000 / 10; double fangchasum = 0L; for (Map.Entry<String, Long> e : dataNodeCount.entrySet()) { fangchasum = fangchasum + Math.pow(e.getValue() - x, 2); } double r = Math.sqrt(fangchasum / 10); System.err.println("标准差:"+r); /** * node:node1,data count:528820 * node:node10,data count:14768 * node:node2,data count:11310 * node:node3,data count:22721 * node:node4,data count:99575 * node:node5,data count:48728 * node:node6,data count:71055 * node:node7,data count:34132 * node:node8,data count:76593 * node:node9,data count:92298 * 标准差:146082.73671998346 */ } public static Long hash(String key) { return murmurhash(key.getBytes()); } public static Long murmurhash(byte[] key) { ByteBuffer buf = ByteBuffer.wrap(key); int seed = 0x1234ABCD; ByteOrder byteOrder = buf.order(); buf.order(ByteOrder.LITTLE_ENDIAN); long m = 0xc6a4a7935bd1e995L; int r = 47; long h = seed ^ (buf.remaining() * m); long k; while (buf.remaining() >= 8) { k = buf.getLong(); k *= m; k ^= k >>> r; k *= m; h ^= k; h *= m; } if (buf.remaining() > 0) { ByteBuffer finish = ByteBuffer.allocate(8).order(ByteOrder.LITTLE_ENDIAN); // for big-endian version, do this first: // finish.position(8-buf.remaining()); finish.put(buf).rewind(); h ^= finish.getLong(); h *= m; } h ^= h >>> r; h *= m; h ^= h >>> r; buf.order(byteOrder); return h; }
学习总结
1.分布缓存可以提高系统的查询性能,但是缓存数据分布不均匀,服务器节点的删除增加导致的缓存不命中 不可避免,通过一致性哈希可以改善上述问题
2.消息队列 最主要的一个作用是系统的解耦,提高系统 的可拓展性。另外可以实现异步,从而提高系统的性能
划线
评论
复制
发布于: 2020 年 07 月 09 日 阅读数: 33
Just顾
关注
还未添加个人签名 2018.05.06 加入
还未添加个人简介
评论