• 一致性哈希算法的研究


      之前由于一直在做客户端开发,对分布式内存缓冲数据存储的原理一直都存有很多疑问,想着无非是哈希算法,或者分级的数据查询,但这两种方式都有很多缺点,使用哈希算法扩展起来很麻烦,分级的话会造成最上级节点瘫痪,导致所有数据请求无法查询。

      最近的新工作需要做一些大数据处理,也了解了一些memcache,HazelCast之类一些缓存系统,从网上搜了一些实现原理的资料,发现其核心是一种叫做一致性哈希的算法,不过我觉得叫“连续hash算法”更合适点,这篇文章上有些详细的介绍 http://blog.csdn.net/sparkliang/article/details/5279393

      C语言版本的算法http://www.codeproject.com/Articles/56138/Consistent-hashing

      Java版本的算法 https://weblogs.java.net/blog/2007/11/27/consistent-hashing

      其实核心算法代码很少,很简单,下面对Java的一致性哈希算法简单做个注释

    import java.util.Collection;
    import java.util.SortedMap;
    import java.util.TreeMap;
    
    public class ConsistentHash<T> {
    //HashFunction普通哈希算法函数
     private final HashFunction hashFunction;
    //numberOfReplicas虚拟节点数量
    private final int numberOfReplicas;
    //环形数值空间,key为server address的hash,value也可以说是服务器地址
    private final SortedMap<Integer, T> circle = new TreeMap<Integer, T>(); //构造,哈希算法函数,壹个真实节点的虚拟节点个数,真实节点集合 public ConsistentHash(HashFunction hashFunction, int numberOfReplicas, Collection<T> nodes) { this.hashFunction = hashFunction; this.numberOfReplicas = numberOfReplicas; for (T node : nodes) { add(node); } } //添加新的真实节点 public void add(T node) { for (int i = 0; i < numberOfReplicas; i++) {
    //产生虚拟节点,并均匀分布出去,虚拟几点是真实节点的地址加上壹个连续数字,并且虚拟节点的value都指向真实节点 circle.put(hashFunction.hash(node.toString()
    + i), node); } } //移除真实节点,并将节点关联的虚拟节点一并删除 public void remove(T node) { for (int i = 0; i < numberOfReplicas; i++) { circle.remove(hashFunction.hash(node.toString() + i)); } } //通过Object key获取其数据存储的服务器 public T get(Object key) { if (circle.isEmpty()) { return null; }
    //获取object key的hash
    int hash = hashFunction.hash(key);
    //节点存在则直接返回hash指向的服务器节点(几率为0.0000...1%),否则则按照一致性哈希算法查找临近服务器节点
    if (!circle.containsKey(hash)) {
    //返回小于当前哈希的有序哈希空间 SortedMap
    <Integer, T> tailMap = circle.tailMap(hash);
    //如果有序哈希空间为空,则返回circle map的第一个key对应的值(因为是个环形),否则则返回有序哈希空间的第一个key对应值 hash
    = tailMap.isEmpty() ? circle.firstKey() : tailMap.firstKey(); } return circle.get(hash); } }
    注:circle中只存储虚节点地址的key-value,不存储object key,这个是刚开始的时候误会了的,我想其他很多人也和我一样被那个算法图误解了,因此前端算法执行的服务器是也是可以横向扩展的。
  • 相关阅读:
    【正则】——作业计算数学运算
    【面向对象】-类和对象作业
    【递归】
    笔记本linux问题记录
    监听器模式(Listener)
    Java引用类型
    Dubbo-服务发布-本地暴露/远程暴露
    完成一个Spring的自定义配置
    Dubbo SPI-Adaptive详解
    Dubbo-动态编译
  • 原文地址:https://www.cnblogs.com/sosopop/p/3296561.html
Copyright © 2020-2023  润新知