分布式理论基础认知:一致性哈希算法(已完成迁移)

一:一致性hash算法
    一致性hash场景描述:
        假如有三台缓存服务器,此时一个数据要缓存到其中一台,并且要一次查询快速定位。一种简单实用的方法就是
        对此时数据标识(key)进行hash取值,然后根据hash值与服务器数量取余获得余数,此数代表了那一台服务器,
        此时数据就缓存在这台服务器上。但是会有个问题,当缓存服务器数量增加或者减少时,原先缓存的数据因为
        服务器数量的增加或者减少,导致余数变化,此时获取缓存肯定是失效的,而且是全局缓存失效,这时导致缓存
        失去意义,这种情况下,出现了一致性hash

    概念:
        上述普通算法是根据服务器数量进行取模运算,而一致性hash就是对 2^32 取模
        把 2^32 想象成一个圆,也就是一个圆上分布了 2^32 个点,又被称为 hash环
        上述hash值对 2^32 取模后(假设为A),会落在 0-2^32-1 上的某一个点,而此时用 服务器ip % 2^32 取模之后的数,
        代表此时服务器所在的点(假设为B),假设 A等于B 或者 A在B的逆时针方向,且靠的最近(hash环是按照顺时针方向
        定义,也就是A会找最近并且在它的顺时针方向上的点,即大的点)
        出现服务器数量增加或者减少后,hash值对于 2^32 取模后的值是相对不变的,也就是缓存的点总是不变,变化的只是
        hash环上某一节点上服务器数的增减,但是影响只限于增减那一段上的,其他地方不会影响。这就是一致性hash相对于普通
        hash的优点

    优点:只影响增减那一段上的数据,其它节点上无感知,正常运行。而普通的取模算法就会导致所有的节点数据异常,一个影响
        部分,一个影响全部


    hash环的偏斜:
        对于服务器ip进行hash取模,很大可能各个节点不是均匀散落在hash环上,这就是hash环的偏斜,由此会导致某一服务器
        上会分布大量数据,而为了防止这种现象,使用“虚拟节点”解决此问题

    虚拟节点:
        虚拟节点是真实节点在hash环上的复制品,一个真实节点可以对应许多的虚拟节点,当然虚拟节点越多,分布就会越均匀,
        数据分布效果越好。
        分析:比如有一百个虚拟节点,从1-100,hash值+ 1-100 ,然后取模,此时大的数取值会大,小的数取值会小,效果也不好
        此时 hash算法要定义一个尽量差异大的,这样相近的hash也会分散开,使得多个节点及其虚拟节点相互混杂,这样
        效果越好,使用虚拟节点就解决了hash环偏斜的问题

二:代码实现及其使用测试
    代码实现:Ketama.java
    使用:
    /*
     * 一致性hash实现:将所有的在线服务都存储到统一 treeMap中,进行负载均衡(路由到其他地址)
     */
    List servers = new ArrayList<>();
    for (String server : servers){
        Logs.info("server router add ketama server({})", server);
        ketama.add(server);
    }
    
    测试:Ketama.java中 main() 方法,详细介绍如何使用


###资料链接
 hash一致性 经典理解:http://www.zsythink.net/archives/1182/

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章