一致性hash算法consistenthashing(代码片段)

PheonixHkbxoic PheonixHkbxoic     2022-10-26     245

关键词:

一致性hash算法Consistent Hashing

对于原有hash算法hash%n
一致性hash算法横空出世
so...

1.话不多说直接上代码,原理或详解自行百度即可

import cn.pheker.utils.UtilElapsedTime;
import cn.pheker.utils.UtilLogger;
import cn.pheker.utils.UtilMD5;

import java.util.*;

/**
 * <pre>
 * author    cn.pheker
 * date      2018/3/19 10:20
 * email     1176479642@qq.com
 * desc      一致性哈希算法
 *
 * </pre>
 */
public class ConsistentHashing 
    
    private static final long MIN_NODE_NUMBER = 0;
    private static final int MAX_NODE_NUMBER = Integer.MAX_VALUE;
    private static int VIRTUAL_NODE_NUMBER;
    
    //真实节点
    private List<Node> realNodes = new LinkedList<Node>();
    //虚拟节点,hash环
    private SortedMap<Integer, VNode> circle = new TreeMap<Integer, VNode>();
    
    private ConsistentHashing(int vnNumber) 
        VIRTUAL_NODE_NUMBER = vnNumber;
    
    
    public static ConsistentHashing build(int vnNumber) 
        return new ConsistentHashing(vnNumber);
    
    
    public ConsistentHashing addNode(Map<String,String> ipPorts) 
        Set<String> ips = ipPorts.keySet();
        Iterator<String> ipite = ips.iterator();
        while(ipite.hasNext())
            String ip = ipite.next();
            addNode(ip, ipPorts.get(ip));
        
        return this;
    
    
    public ConsistentHashing addNode(String ip, int port) 
        addNode(ip, String.valueOf(port));
        return this;
    
    
    public ConsistentHashing addNode(String ip, String port) 
        Node node = new Node(ip, port);
        if (!realNodes.contains(node)) 
            realNodes.add(node);
            UtilLogger.println("[Node]:"+node.toString()+" Hash:"+node.hashFNV1_32());
            //生成VIRTUAL_NODE_NUMBER个虚拟节点
            for (int i = 0; i < VIRTUAL_NODE_NUMBER; i++) 
                VNode vNode = node.createVNode(i);
                circle.put(vNode.hashFNV1_32(), vNode);
                UtilLogger.println("\\t[VNode]:"+vNode.toString()+" Hash:"+vNode.hashFNV1_32());
            
        
        return this;
    
    
    public void removeNode(String ip,String port) 
        Node node = new Node(ip, port);
        for(int i = 0;i<VIRTUAL_NODE_NUMBER;i++) 
            VNode vNode = node.createVNode(i);
            circle.remove(vNode.hashFNV1_32());
        
        circle.remove(node.hashFNV1_32());
    
    
    public VNode getNode(String ip, int port) 
        return getNode(ip, String.valueOf(port));
    
    
    public VNode getNode(String ip, String port) 
        Node node = new Node(ip, port);
        int hash = node.hashFNV1_32();
        if(circle.isEmpty()) return null;
        SortedMap<Integer, VNode> tailMap = circle.tailMap(hash);
        int hashKey;
        if (tailMap.isEmpty()) 
            hashKey = circle.firstKey();
        else 
            hashKey = tailMap.firstKey();
        //顺时针最近节点
        VNode vNode = circle.get(hashKey);
        UtilLogger.println(String.format("[%s]:%s ==> [%s]:%s",
                node.hashFNV1_32(),node,vNode.hashFNV1_32(),vNode));
        return vNode;
    
    
    
    /**
     * 第个节点都是一个服务器主机
     */
    public class Node 
        String ip;
        String port;
        
        public Node(String ip, String port) 
            this.ip = ip;
            this.port = port;
        
        
        public String getIp() 
            return ip;
        
        
        public void setIp(String ip) 
            this.ip = ip;
        
        
        public String getPort() 
            return port;
        
        
        public void setPort(String port) 
            this.port = port;
        
    
        public VNode createVNode(int vnNumber) 
            return new VNode(ip, port, vnNumber);
        
        
        @Override
        public boolean equals(Object o) 
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            Node vNode = (Node) o;
            return Objects.equals(ip, vNode.ip) &&
                    Objects.equals(port, vNode.port);
        

        @Override
        public String toString() 
            return ip + ":" + port;
        
    
        /**
         *使用FNV1_32_HASH算法计算服务器的Hash值,这里不能重写hashCode的方法
         */
        public int hashFNV1_32()
            String str = UtilMD5.MD5(this.toString());
            final int p = 16777619;
            int hash = (int)2166136261L;
            for (int i = 0; i < str.length(); i++)
                hash = (hash ^ str.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;
        
    
    
    /**
     * 虚拟节点
     */
    public class VNode extends Node
        int number;
    
        public VNode(String ip, String port,int number) 
            super(ip, port);
            this.number = number;
        
    
        public Node toNode() 
            return new Node(ip,port);
        
    
        @Override
        public boolean equals(Object o) 
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            if (!super.equals(o)) return false;
            VNode vNode = (VNode) o;
            return number == vNode.number;
        
    
        @Override
        public int hashCode() 
            return Objects.hash(number);
        
    
        @Override
        public String toString() 
            return ip + ":" + port+"#"+number;
        
    
    
    /**
     * 校验hash分布均匀性
     * @return
     */
    public float check() 
        Set<Integer> ks = circle.keySet();
        int size = ks.size();
        long sum = 0L;
        for (int hash : ks) 
            sum += hash;
        
        double percent = size == MIN_NODE_NUMBER ? MIN_NODE_NUMBER :
                (100*2*sum/size)/MAX_NODE_NUMBER;
        return Float.valueOf(String.format("%.2f", percent));
    
    
    public static void main(String[] args) 
        UtilElapsedTime.test(() -> 
            ConsistentHashing ch = ConsistentHashing.build(3);
            //添加节点
            UtilLogger.println("------------添加节点----------------");
            ch.addNode("10.96.74.187", 80);
            ch.addNode("127.0.0.1", 8080);
            ch.addNode("243.15.155.0", 2150);
            ch.addNode("243.15.155.1", 2150);
        
            UtilLogger.println("------------是否均匀----------------");
            UtilLogger.println(ch.check() + "%");
        
            //获取节点
            UtilLogger.println("------------获取节点----------------");
            ch.getNode("10.96.74.187", 80);
            ch.getNode("123.1.122.253", 44);
            ch.getNode("234.67.80.219", 3306);
            return "耗时计算完成";
        );
    
    



2.结果

------------添加节点----------------
[Node]:10.96.74.187:80 Hash:1695118842
	[VNode]:10.96.74.187:80#0 Hash:1661313686
	[VNode]:10.96.74.187:80#1 Hash:1283046442
	[VNode]:10.96.74.187:80#2 Hash:564332117
[Node]:127.0.0.1:8080 Hash:678080562
	[VNode]:127.0.0.1:8080#0 Hash:1731933288
	[VNode]:127.0.0.1:8080#1 Hash:1369405387
	[VNode]:127.0.0.1:8080#2 Hash:200594664
[Node]:243.15.155.0:2150 Hash:1175061629
	[VNode]:243.15.155.0:2150#0 Hash:134880260
	[VNode]:243.15.155.0:2150#1 Hash:1677894747
	[VNode]:243.15.155.0:2150#2 Hash:522817245
[Node]:243.15.155.1:2150 Hash:1305999210
	[VNode]:243.15.155.1:2150#0 Hash:1193457699
	[VNode]:243.15.155.1:2150#1 Hash:279279823
	[VNode]:243.15.155.1:2150#2 Hash:2115663065
------------是否均匀----------------
98.0%
------------获取节点----------------
[1695118842]:10.96.74.187:80 ==> [1731933288]:127.0.0.1:8080#0
[601034131]:123.1.122.253:44 ==> [1193457699]:243.15.155.1:2150#0
[508181784]:234.67.80.219:3306 ==> [522817245]:243.15.155.0:2150#2
[23.104187ms] 耗时计算完成

Process finished with exit code 0

3.注意事项

代码中用到了几个工具类UtilMD5,UtilLogger换成自己的即可,UtilElapsedTime用于计算耗时,可以直接去掉。

4.参考链接

对一致性Hash算法,Java代码实现的深入研究
白话解析:一致性哈希算法 consistent hashing

hash一致性算法底层原理

大纲Hash取余算法判定哈希算法好坏的四个定义一致性Hash算法的两大设计 Hash取余算法hash(Object.key)%N,hash值随Object.key、N的变化而变化。如果有节点(集群中节点增减太正常)发生变化,几乎重新分配,意味着所有已经分配好... 查看详情

一致性hash算法

...构:核心原理与案例分析》时,第一次比较完备的了解了一致性hash算法, 一致性哈希算法早在1997年由麻省理工学院提出的一种分布式哈希(DHT)实现算法,而该算法的核心是将hash环的数据结构实现KEY到缓存服务器的HASH映... 查看详情

一致性hash算法

参考帖https://www.cnblogs.com/mushroom/p/4472369.html hash一致性算法hash函数的一种,他的目的在于实现负载均衡,并且每次访问的目标具有一致性,举个例子来说,根据客户端请求ip,经过hash一致性算法,每次计算出来的一致性hash值... 查看详情

对一致性hash算法,java代码实现的深入研究

原文:http://www.cnblogs.com/xrq730/p/5186728.html一致性Hash算法关于一致性Hash算法,在我之前的博文中已经有多次提到了,MemCache超详细解读一文中"一致性Hash算法"部分,对于为什么要使用一致性Hash算法、一致性Hash算法的算法原理做了... 查看详情

算法一致性hash/hash环

...务器机器时候,用户id与服务器的映射关系会大量失效。一致性hash则利用hash环对其进行了改进。什么是一致性hash/hash 查看详情

一致性hash算法在memcached中的使用

...的memcacheclient(这里我看的spymemcache的源代码)。使用了一致性hash算法ketama进行数据存储节点的选择。与常规的hash算法思路不同。仅仅是对我们要存储数据的key进行hash计算,分配到不同节点存储。一致性hash算法是对我们要存储... 查看详情

hash一致性算法

一致性hash算法是,1097麻省理工提出的分布式hashDHT实现算法,极倔internet的热点问题 平衡性hash结果尽可能的分布到所有的缓存中去,缓冲空间利用率最高单调性保持已有的缓存能映射到对应的位置,新加入的缓存能加入新的... 查看详情

算法一致性hash/hash环

...务器机器时候,用户id与服务器的映射关系会大量失效。一致性hash则利用hash环对其进行了改进。什么是一致性hash/hash环一致性hash算法是对2^32取模,将整个hash空间组织成一个虚拟的圆环,因此hash函数的值空间为:0~2^32-1(32位无... 查看详情

关于什么是一致性hash算法

...要么需要遍历所有缓存服务器。不够灵活。所以就出现了一致性hash算法,来解决这样的问题。Hash环,如下图所示:一致性Hash算法是key的ha 查看详情

hash一致性算法

Hash一致性算法序在进行一般的负载均衡、查询负载、分布式缓存、Shuffle等等中的时候,都需要计算这条数据/请求/查询去往哪一个节点。一般来说我们直接进行MessageKey取Hash后的结果对后续节点数进行取余操作就能标识这条... 查看详情

一致性hash算法consistenthashing(代码片段)

一致性hash算法ConsistentHashing对于原有hash算法hash%nso...1.话不多说直接上代码,原理或详解自行百度即可importcn.pheker.utils.UtilElapsedTime;importcn.pheker.utils.UtilLogger;importcn.pheker.utils.UtilMD5;importjava.util.*;/***<pre 查看详情

一致性hash算法背景

一致性Hash算法背景  一致性哈希算法在1997年由麻省理工学院的Karger等人在解决分布式Cache中提出的,设计目标是为了解决因特网中的热点(Hotspot)问题,初衷和CARP十分类似。一致性哈希修正了CARP使用的简单哈希算法带来的问题... 查看详情

架构实践使用golang实现一致性hash算法代码

【架构实践】使用golang实现一致性Hash算法代码文章目录【架构实践】使用golang实现一致性Hash算法代码分布式系统中的一致性Hash算法具体是什么?再详细一点讲讲一致性Hash算法存在的一些问题一致性Hash算法都有哪些实际的应用... 查看详情

一致性hash算法

一致性哈希算法在1997年由麻省理工学院提出的一种分布式哈希(DHT)实现算法,设计目标是为了解决因特网中的热点(Hotspot)问题,初衷和CARP十分类似。一致性哈希修正了CARP使用的简单哈希算法带来的问题,使得分布式哈希(DHT... 查看详情

一致性hash算法

一致性哈希算法在1997年由麻省理工学院提出的一种分布式哈希(DHT)实现算法,设计目标是为了解决因特网中的热点(Hotspot)问题,初衷和CARP十分类似。一致性哈希修正了CARP使用的简单哈希算法带来的问题,使得分布式哈希(DHT... 查看详情

nginx负载均衡之一致性hash,普通hash

...衡原理  ngx_http_upstream_hash_module支持普通的hash及一致性hash两种负载均衡算法,默认的是普通的hash来进行负载均衡。  nginx普通的hash算法支持配置http变量值作为hash值计算的key,通过hash计算得出的hash值和总权重... 查看详情

一致性hash算法

https://blog.csdn.net/cb_lcl/article/details/81448570实现https://www.cnblogs.com/fanguangdexiaoyuer/p/6549306.html 查看详情

一致性hash算法原理,java实现,及用途

学习记录:一致性Hash算法原理及java实现:https://blog.csdn.net/suifeng629/article/details/81567777一致性Hash算法介绍,原理,及使用场景:https://blog.csdn.net/cbmljs/article/details/88021598纯转载,侵删 查看详情