一致性HASH

前面提到分布式数据库数据分区规则有

【节点取余分区】

【一致性哈希分区】

【虚拟hash槽分区】

一致性HASH原理:在处理负载策略时:

  • 一个hash环,从0到正整数
  • 四个服务器ip计算的hash值肯定会落到这个hash环上的某一个点
  • 根据hash(用户id)计算路由规则(hash值),然后看hash值落到了hash环的那个地方,根据hash值在hash环上的位置顺时针找距离最近的ip作为路由ip

数据分区也是同理。

如图:

  • user1的请求会落到服务器ip1进行处理
  • user2,user3的请求会落到服务器ip3进行处理
  • user4的请求会落到服务器ip4进行处理

一致性HASH_第1张图片

public class IdenticalHash {

    //服务器列表
    public static String[] serverIps = {"192.168.0.1",
            "88.89.90.91", "77.78.79.80", "127.0.0.1"};

    //key表示服务器的hash值,value表示服务器
    public static TreeMap hashRing = new TreeMap();


    //通过用户ip得到处理该ip的服务器地址
    public static String getServerByIdHash(String userId) {
        int hash = hash(userId);
        //得到大于该Hash值的所有Map
        SortedMap moreThanIpMap = hashRing.tailMap(hash);
        if (moreThanIpMap.isEmpty()) {
            //如果没有比该key的hash值大的,则从第一个node开始
            return hashRing.get(hashRing.firstKey());
        }
        //第一个Key就是顺时针过去离node最近的那个结点
        return moreThanIpMap.get(moreThanIpMap.firstKey());
    }

    //根据key获取hash值(复用hashmap中的hash算法)
    public static int hash(String str) {
        int h;
        return (str == null) ? 0 : (h = str.hashCode()) ^ (h >>> 16);
    }

    //将服务器ip放到hash环中
    public static void putHashRing() {
        for (int i = 0; i < serverIps.length; i++) {
            int hash = hash(serverIps[i]);
            hashRing.put(hash, serverIps[i]);
            System.err.println(serverIps[i] + " 在hash环中的位置:" + hash);
        }
    }

    public static void main(String[] args) {

        putHashRing();
        String[] userIds = {"1241414", "42452356", "4214", "777789"};
        for (int i = 0; i < userIds.length; i++) {
            System.out.println("用户id:" + userIds[i] + " 的hash值为" + hash(userIds[i])
                    + ", 交由服务器:" + getServerByIdHash(userIds[i]) + " 处理");
        }
    }
}

上诉hash环中的服务器ip分配不均。也可能会导致某服务器处理大量的请求,有服务器会闲置

均匀一致性hash

均匀一致性hash的目标是如果服务器有N台,客户端的hash值有M个,那么每个服务器应该处理大概M/N个用户的。也就是每台服务器负载尽量均衡.

你可能感兴趣的:(Redis)