zoukankan      html  css  js  c++  java
  • 分布式hash相关内容

    Hash算法相关内容

    ⾸先有⼀条直线,直线开头和结尾分别定为为1和2的32次⽅减1,这相当于⼀个地址,对于这样⼀条
    线,弯过来构成⼀个圆环形成闭环,这样的⼀个圆环称为hash环。我们把服务器的ip或者主机名求
    hash值然后对应到hash环上,那么针对客户端⽤户,也根据它的ip进⾏hash求值,对应到环上某个位
    置,然后如何确定⼀个客户端路由到哪个服务器处理呢?按照顺时针⽅向找最近的服务器节点
    假如将服务器3下线,服务器3下线后,原来路由到3的客户端重新路由到服务器4,对于其他客户端没有
    影响只是这⼀⼩部分受影响(请求的迁移达到了最⼩,这样的算法对分布式集群来说⾮常合适的,避免
    了⼤量请求迁移 )
    增加服务器5之后,原来路由到3的部分客户端路由到新增服务器5上,对于其他客户端没有影响只是这
    ⼀⼩部分受影响(请求的迁移达到了最⼩,这样的算法对分布式集群来说⾮常合适的,避免了⼤量请求
    迁移 )
    1)如前所述,每⼀台服务器负责⼀段,⼀致性哈希算法对于节点的增减都只需重定位环空间中的⼀⼩
    部分数据,具有较好的容错性和可扩展性。
    但是,⼀致性哈希算法在服务节点太少时,容易因为节点分部不均匀⽽造成数据倾斜问题。例如系统中
    只有两台服务器,其环分布如下,节点2只能负责⾮常⼩的⼀段,⼤量的客户端
    请求落在了节点1上,这就是数据(请求)倾斜问题
    2)为了解决这种数据倾斜问题,⼀致性哈希算法引⼊了虚拟节点机制,即对每⼀个服务节点计算多个
    哈希,每个计算结果位置都放置⼀个此服务节点,称为虚拟节点。
    具体做法可以在服务器ip或主机名的后⾯增加编号来实现。⽐如,可以为每台服务器计算三个虚拟节
    点,于是可以分别计算 “节点1的ip#1”、“节点1的ip#2”、“节点1的ip#3”、“节点2的ip#1”、“节点2的
    ip#2”、“节点2的ip#3”的哈希值,于是形成六个虚拟节点,当客户端被路由到虚拟节点的时候其实是被
    路由到该虚拟节点所对应的真实节点

    一致性Hash算法的代码

    普通hash算法

    /**
    * 普通Hash算法实现
    */
    public class GeneralHash {
    public static void main(String[] args) {
    // 定义客户端IP
    String[] clients = new String[]
    {"10.78.12.3","113.25.63.1","126.12.3.8"};
    // 定义服务器数量
    int serverCount = 5;// (编号对应0,1,2)
    // hash(ip)%node_counts=index
    //根据index锁定应该路由到的tomcat服务器
    for(String client: clients) {
    int hash = Math.abs(client.hashCode());
    int index = hash%serverCount;
    System.out.println("客户端:" + client + " 被路由到服务器编号为:" + index);
     }
     }
    }
    

    一致性hash算法不带虚拟节点

    public class ConsistentHashNoVirtual {
    public static void main(String[] args) {
    //step1 初始化:把服务器节点IP的哈希值对应到哈希环上
    // 定义服务器ip
    String[] tomcatServers = new String[]
    {"123.111.0.0","123.101.3.1","111.20.35.2","123.98.26.3"};
    SortedMap<Integer,String> hashServerMap = new TreeMap<>();
    for(String tomcatServer: tomcatServers) {
    // 求出每⼀个ip的hash值,对应到hash环上,存储hash值与ip的对应关系
    int serverHash = Math.abs(tomcatServer.hashCode());
    // 存储hash值与ip的对应关系
    hashServerMap.put(serverHash,tomcatServer);
     }
    //step2 针对客户端IP求出hash值
    // 定义客户端IP
    String[] clients = new String[]
    {"10.78.12.3","113.25.63.1","126.12.3.8"};
    for(String client : clients) {
    int clientHash = Math.abs(client.hashCode());
    //step3 针对客户端,找到能够处理当前客户端请求的服务器(哈希环上顺时针最
    近)
    // 根据客户端ip的哈希值去找出哪⼀个服务器节点能够处理()
    SortedMap<Integer, String> integerStringSortedMap =
    hashServerMap.tailMap(clientHash);
    if(integerStringSortedMap.isEmpty()) {
    // 取哈希环上的顺时针第⼀台服务器
    Integer firstKey = hashServerMap.firstKey();
    System.out.println("==========>>>>客户端:" + client + " 被
    路由到服务器:" + hashServerMap.get(firstKey));
     }else{
    Integer firstKey = integerStringSortedMap.firstKey();
    System.out.println("==========>>>>客户端:" + client + " 被
    路由到服务器:" + hashServerMap.get(firstKey));
     }
     }
     }
    }
    

    一致性hash算法带虚拟节点

    public class ConsistentHashWithVirtual {
    public static void main(String[] args) {
    //step1 初始化:把服务器节点IP的哈希值对应到哈希环上
    // 定义服务器ip
    String[] tomcatServers = new String[]
    {"123.111.0.0","123.101.3.1","111.20.35.2","123.98.26.3"};
    SortedMap<Integer,String> hashServerMap = new TreeMap<>();
    // 定义针对每个真实服务器虚拟出来⼏个节点
    int virtaulCount = 3;
    for(String tomcatServer: tomcatServers) {
    // 求出每⼀个ip的hash值,对应到hash环上,存储hash值与ip的对应关系
    int serverHash = Math.abs(tomcatServer.hashCode());
    // 存储hash值与ip的对应关系
    hashServerMap.put(serverHash,tomcatServer);
    // 处理虚拟节点
    for(int i = 0; i < virtaulCount; i++) {
    int virtualHash = Math.abs((tomcatServer + "#" + i).hashCode());
    hashServerMap.put(virtualHash,"----由虚拟节点"+ i + "映射过
    来的请求:"+ tomcatServer);
     }
     }
    //step2 针对客户端IP求出hash值
    // 定义客户端IP
    String[] clients = new String[]
    {"10.78.12.3","113.25.63.1","126.12.3.8"};
    for(String client : clients) {
    int clientHash = Math.abs(client.hashCode());
    //step3 针对客户端,找到能够处理当前客户端请求的服务器(哈希环上顺时针最
    近)
    // 根据客户端ip的哈希值去找出哪⼀个服务器节点能够处理()
    SortedMap<Integer, String> integerStringSortedMap =
    hashServerMap.tailMap(clientHash);
    if(integerStringSortedMap.isEmpty()) {
    // 取哈希环上的顺时针第⼀台服务器
    Integer firstKey = hashServerMap.firstKey();
    System.out.println("==========>>>>客户端:" + client + " 被
    路由到服务器:" + hashServerMap.get(firstKey));
     }else{
    Integer firstKey = integerStringSortedMap.firstKey();
    System.out.println("==========>>>>客户端:" + client + " 被
    路由到服务器:" + hashServerMap.get(firstKey));
     }
     }
     }
    }
    

    欢迎搜索关注本人与朋友共同开发的微信面经小程序【大厂面试助手】和公众号【微瞰技术】,以及总结的分类面试题https://github.com/zhendiao/JavaInterview

    file
    file

  • 相关阅读:
    select、poll和epoll
    Linux 常用命令之文件和目录
    SmartPlant Review 帮助文档机翻做培训手册
    SmartPlant Foundation 基础教程 3.4 菜单栏
    SmartPlant Foundation 基础教程 3.3 标题栏
    SmartPlant Foundation 基础教程 3.2 界面布局
    SmartPlant Foundation 基础教程 3.1 DTC登陆界面
    SmartPlant Foundation 基础教程 1.4 SPF架构
    SmartPlant Foundation 基础教程 1.3 SPF其他功能
    SmartPlant Foundation 基础教程 1.2 SPF集成设计功能
  • 原文地址:https://www.cnblogs.com/zhendiao/p/14920368.html
Copyright © 2011-2022 走看看