zoukankan      html  css  js  c++  java
  • 一致性哈希算法的研究

    一致性哈希算法的研究

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

      最近的新工作需要做一些大数据处理,也了解了一些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,这个是刚开始的时候误会了的,我想其他很多人也和我一样被那个算法图误解了,因此前端算法执行的服务器是也是可以横向扩展的。
    复制代码
  • 相关阅读:
    17 中国天气网信息爬取
    16 select和css选择器(提取元素详解)
    15 Beautiful Soup(提取数据详解find_all())
    linux命令之tail命令
    Linux命令之ps命令
    Android使用Fiddler模拟弱网络环境测试
    发送邮件smtplib,email,邮件头header,定时器schedule,爬虫requests(转)
    python实现发送带附件的邮件 (转载)
    VMware centos 7 图形界面的分辨率和终端字体大小设置(转)
    docker-compose: 未找到命令
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/3297035.html
Copyright © 2011-2022 走看看