分布式一致性Hash算法原理及实现【负载均衡】

news2024/10/1 9:33:28

文章目录

  • 一致性Hash原理
  • 提高容错性和和扩展性
  • 一致性Hash实现
    • 思路
    • 代码

一致性Hash原理

简单来说,一致性Hash算法将整个哈希值空间组织成一个虚拟的圆环
如假设某哈希函数 H 的值空间为 0 ~ 2^32-1(即哈希值是一个32位无符号整形)

提高容错性和和扩展性

1,用户访问时,根据用户的 IP 使用上面相同的函数 Hash计算出哈希值,并确定此数据在环上的位置,从此位置沿环顺时针行走,遇到的第一台服务器就是其应该定位到的服务器。
2,注意这里提高容错性,用到了虚拟节点设置在圆环上,这个虚拟节点本质就是与物理节点进行绑定的一个节点,这里想到的是map形式进行绑定

一致性Hash实现

思路

1.hash值是一个非负整数,把非负整数的值范围做成一个圆环;
2.对集群的节点的某个属性求hash值(如节点名称),根据hash值把节点放到环上;
3.对数据的key求hash值,一样的把数据也放到环上,按顺时针方向,找离他最近的节点,就存储到这个节点上。(这个圆环相当于有序的集合,且为了方便查找,存储结构使用treeMap)

圆环中的存储的数据节点结构如下图所示:
在这里插入图片描述

代码

public class Node {

    private String id;

    private String name;

    private List<String> datas = new ArrayList<>();


    public Node() { }

    public Node(String id, String name) {
        this.id = id;
        this.name = name;
    }

    public void setId(String id) {
        this.id = id;
    }

    public void setName(String name) {
        this.name = name;
    }


    public String getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public void setDatas(List<String> datas) {
        this.datas = datas;
    }

    public List<String> getDatas() {
        return datas;
    }

    @Override
    public String toString() {
        return "Node【" +
                "id='" + id + '\'' +
                ", name='" + name + '\'' +
                ", datas=" + datas.toString() +
                '】';
    }
}
@Data
public class HashUtilServe {

    // 存放物理节点
    private List<Node> nodeList = new ArrayList<>();

    // 设置每个物理节点的虚拟节点50个
    private int virtalNodeNum = 50;

    // 物理节点和虚拟hash节点key进行关联
    private HashMap<Node,List<Integer>> virNode = new HashMap<>();

    // 定义一个hash集合存放节点
    private SortedMap<Integer,Node> sortedMap = new TreeMap<>();

    /**
     * 增加服务节点
     * @param node
     */
    public  void  createServe(Node node){
        // 加入物理节点
        nodeList.add(node);
        ArrayList<Integer> hashlist = new ArrayList<>();
        // 创建虚拟节点
        for(int i=0; i<virtalNodeNum; i++){
            int hashValue = FNVHash1(node.getId() + "-" + i);
            hashlist.add(hashValue);
            sortedMap.put(hashValue,node);
        }virNode.put(node,hashlist);
    }

    /**
     * 删除服务节点
     * @param node
     */
    public void deleteServe(Node node){
        // 删除物理节点
        nodeList.remove(node);
        // 删除对应的物理节点
        List<Integer> hashs = virNode.get(node);
        for (Integer hash : hashs) {
            sortedMap.remove(hash);
        }
        // 删除关联表
        virNode.remove(node);
    }

    /**
     * 查好数据对应服务节点
     * @param data
     * @return
     */
    public Node findServe(String data){

        // 对数据进行hash
        int hashValue = FNVHash1(data);

        // 获取【key>=hashvalue】的虚拟节点的map
        SortedMap<Integer, Node> findedMap = sortedMap.tailMap(hashValue);

        if(findedMap.isEmpty()){
            // 只有一台服务器节点并且当前数据缓存的服务器宕机了,找不到服务节点
            return null;
           //  return sortedMap.get(sortedMap.firstKey());
        }
        // 拿最近一台的服务器节点
        return  findedMap.get(findedMap.firstKey());
    }

    /**
     * 分布式缓存存储数据
     * @param data
     * @return
     */
    public Node saveData(String data){

        // 对数据进行hash
        int hashValue = FNVHash1(data);

        // 获取【key>=hashvalue】的虚拟节点的map
        SortedMap<Integer, Node> findedMap = sortedMap.tailMap(hashValue);

        Node node =new Node();
        if(findedMap.isEmpty()){
            // 只有一台服务器节点
            node = sortedMap.get(sortedMap.firstKey());
        }
        // 拿最近一台的服务器节点
        node = findedMap.get(findedMap.firstKey());

        // 将数据缓存到对应服务节点中
        List<String> datas = node.getDatas();
        datas.add(data);
        node.setDatas(datas);
        return node;
    }

    // 散列工具类
    public int FNVHash1(String data) {
        final int p = 16777619;
        int hash = (int) 2166136261L;
        for (int i = 0; i < data.length(); i++)
            hash = (hash ^ data.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 DemoPract {
    public static void main(String[] args) {

        // 创建三台服节点对象
        Node serv1 = new Node("192.168.0.1", "serv1");
        Node serv2 = new Node("192.168.0.5", "serv2");
        Node serv3 = new Node("192.168.0.11", "serv3");

        HashUtilServe hashUtil = new HashUtilServe();
        // 将服务器添加到Hash环上
        hashUtil.createServe(serv1);
        hashUtil.createServe(serv2);
        hashUtil.createServe(serv3);

        // 缓存数据到服务节点上
        hashUtil.saveData("1今天是个好日子");
        hashUtil.saveData("2理想要有的");
        hashUtil.saveData("3很厉害的事情");
        hashUtil.saveData("啊哈java才是最牛的");

        Node serve33 = hashUtil.findServe("3很厉害的事情");
        System.out.println(serve33.toString());

        // 删除服务节点3
        hashUtil.deleteServe(serv3);
        System.out.println("---------删除服务3节点----------------");

        Node serve1 = hashUtil.findServe("1今天是个好日子");
        Node serve2 = hashUtil.findServe("2理想要有的");
        Node serve3 = hashUtil.findServe("3很厉害的事情");
        System.out.println(serve1.toString());
        System.out.println(serve2.toString());
        System.out.println(serve3.toString());

    }
}

测试结果如下:
如图所示:可以看到服务器3宕机之后,再查询原来缓存到到服务3的数据,发现三号服务器的缓存数据查询不到了
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/485133.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

什么是POTDR?POTDR在光缆线路维护中有哪些应用

1 引言 OTDR&#xff08;Optical Time Domain Reflectometer&#xff0c;光时域反射仪&#xff09;是光缆线路工程及维护中的常用仪表&#xff0c;是利用光信号在光纤中传输时的瑞利散射和菲涅尔反射&#xff0c;通过反射曲线来了解光纤沿长度的损耗分布情况&#xff0c;可测量…

基于C#编程建立泛型Matrix数据类型及对应处理方法

一、简介 上一篇文档中描述了如何写一个Vector<T>类&#xff0c;本次在上一篇文档基础上&#xff0c;撰写本文&#xff0c;介绍如何书写一个泛型Matrix&#xff0c;可以应用于int、double、float等C#数值型的matrix。 本文所描述的Matrix<T>是一个泛型&#xff0c;…

一个人在家怎么赚钱?普通人如何通过网络实现在家就能赚钱

近年来&#xff0c;随着互联网的飞速发展&#xff0c;嗅觉敏锐的人只要使用互联网就可以快乐地赚钱。一般来说&#xff0c;网上赚钱的投资较少&#xff0c;有时有一台能上网的电脑或手机就够了&#xff0c;所以大家有时称其为“无成本或低成本网赚”。今天就分享一个人在家如何…

23种设计模式第一章:单例模式

这里写自定义目录标题 一 单例模式1 静态常量饿汉式2 静态代码块饿汉式3 线程不安全懒汉式4 线程安全懒汉式线程安全&#xff0c;同步方法线程安全&#xff0c;同步代码块 5 doubleCheck&#xff08;双重检查&#xff0c;推荐使用&#xff09;6 静态内部类7 枚举 一 单例模式 …

K8s 安全是云安全的未来

导语 到 2025 年&#xff0c;保护 Kubernetes (K8s) 将被认为是云安全最重要的方面。 在最成功的组织中&#xff0c;CTO 和 CISO 已经意识到 Kubernetes 安全的重要性。 但是&#xff0c;虽然 Kubernetes 已经占 CTO 云支出的很大一部分&#xff0c;但 CISO 仍然有所落后。 大…

基于web的课程重难点掌握情况分析系统

1&#xff0e;系统登录&#xff1a;系统登录是用户访问系统的路口&#xff0c;设计了系统登录界面&#xff0c;包括用户名、密码和验证码&#xff0c;然后对登录进来的用户判断身份信息&#xff0c;判断是管理员用户还是普通用户。 2&#xff0e;系统用户管理&#xff1a;不管是…

19.考虑柔性负荷的综合能源系统日前优化调度模型

说明书 MATLAB代码&#xff1a;考虑柔性负荷的综合能源系统日前优化调度模型 关键词&#xff1a;柔性负荷 需求响应 综合需求响应 日前优化调度 综合能源系统 参考文档&#xff1a;《考虑用户侧柔性负荷的社区综合能源系统日前优化调度》参考柔性负荷和基础模型部分&#xf…

脑电信号特征提取方法与应用

前言 脑电图(EEG)信号在理解与脑功能和脑相关疾病的电活动方面发挥着重要作用。典型的脑电信号分析流程如下&#xff1a;(1)数据采集&#xff1b;(2)数据预处理&#xff1b;(3)特征提取&#xff1b;(4)特征选择&#xff1b;(5)模型训练与分类&#xff1b;(6)性能评估。当信号分…

SpringClouid学习笔记(正在更新中...)

目录 SpringCloud1、微服务1.1、定义1.2、特性单体应用微服务应用 1.3、微服务架构演变&#xff08;RPC&#xff09;1.4、微服务解决方案 2、SpringCloud2.1、什么是SpringCloud官方定义DemoSpringCloud版本和SpringBoot版本选择 3、环境搭建环境说明构建方式开始构建 4、服务注…

全注解下的SpringIoc 续3-属性文件的使用

在Spring Boot中使用属性文件&#xff0c;可以采用默认的application.properties文件&#xff0c;也可以使用自定义的配置文件&#xff0c;下面让我们一起来看看这两个的使用。 使用默认的application.properties文件 这个配置文件是Spring Boot默认会加载的&#xff0c;所以…

自动抓取QQ好友列表?Windows UIA教你轻松实现

目录&#xff1a;导读 引言 选择Windows UIA框架进行自动化测试的原因 查找窗口 读取QQ软件的好友列表 结语 引言 每个使用QQ的人都有自己的好友列表&#xff0c;但是如果你想要查看所有好友信息&#xff0c;手动一个个点击会非常浪费时间。那么有没有什么快速获取好友列…

【openGauss实战12】表空间管理

&#x1f4e2;&#x1f4e2;&#x1f4e2;&#x1f4e3;&#x1f4e3;&#x1f4e3; 哈喽&#xff01;大家好&#xff0c;我是【IT邦德】&#xff0c;江湖人称jeames007&#xff0c;10余年DBA及大数据工作经验 一位上进心十足的【大数据领域博主】&#xff01;&#x1f61c;&am…

【总线】IIC学习笔记

【总线】IIC学习笔记 参考链接IIC总线介绍IIC总线时序1.空闲信号2. 启动信号与停止信号3.数据的有效性4.应答信号5.七位地址传输 IIC读写过程&#xff08;AT24C02举例&#xff09;IIC读过程IIC写过程 正点原子IIC驱动问题1、IIC停止信号问题2、IIC-AT24C02的器件地址发送的疑惑…

OJ搭建配置 功能速查手册

服务器配置 腾讯云 2H4G 5M 60GB 轻量应用服务器 承载大约 200~400人使用&#xff0c;经过压力测试&#xff0c;评测并发速度可满足130人左右的在线比赛。 系统镜像选 Ubuntu 22.04 LTS。 用户管理 一、批量导入&#xff08;从方便管理角度建议以 学生姓名 作为 用户名 &am…

网络安全之黄金票据,白银票据

前言&#xff1a;今天来给大家讲讲黄金票据和白银票据Kerberos认证#金票Golden ticket# 原理#伪造金票的场景和所需条件#利用方式#银票SILVER TICKET# 原理#伪造银票所需条件#金票和银票的区别# 获取的权限不同#认证流程不同#加密方式不同# 前言&#xff1a;今天来给大家讲讲黄…

Unity 3D 学习笔记(1)

文章目录 1.Unity 3D 概述2.Unity的安装过程3.Unity 3D 的项目管理4.Unity 3D 中的场景5.Unity 3D 的界面组成 1.Unity 3D 概述 Unity 3D简介&#xff1a;Unity 3D是虚拟现实行业中使用率较高的一款开发引擎&#xff0c;由Unity Technology公司开发。通过Unity&#xff0c;开发…

手动实现 Spring 底层机制【初始化 IOC容器+依赖注入+BeanPostProcessor 机制+AOP】

目录 手动实现 Spring 底层机制【初始化 IOC容器依赖注入BeanPostProcessor 机制AOP】 前面我们实际上已经用代码简单实现了 代码演示使用框架 创建一个maven项目 创建UserAction类 创建UserDao类 创建UserService类 创建beans.xml 说明 创建AppMain类 运行效果 如图…

《汇编语言》- 读书笔记 - 第2章-寄存器

《汇编语言》- 读书笔记 - 第2章-寄存器 2.0 8086CPU 寄存器段地址:偏移地址 2.1 通用寄存器2.2 字在寄存器中的存储2.3 几条汇编指令表2.1汇编指令举例表2.2 程序段中指令的执行情况之一问题 2.1表2.3 程序段中指令的执行情况之二问题 2.2 2.4 物理地址2.5 16位结构的CPU2.6 8…

数据埋点1

文章目录 1 什么是数据埋点2 为什么需要数据埋点3 数据埋点能采集哪些用户数据4 数据埋点的分类及方式5 主流的数据上报技术5.1 客户端上报5.2 服务端获取 1 什么是数据埋点 互联网的海量数据是通过数据埋点技术采集用户行为数据而产生的&#xff0c;用户行为数据采集及上报流…

我又不当程序员还要学Python吗?人工智能AI的出现我知道,我错了

Python&#xff08;可读音&#xff1a;派森&#xff09; 时代要淘汰你&#xff0c;连招呼都不会打&#xff01; 这句话近些年我们常在媒体上听到&#xff0c;有点残酷&#xff0c;但却又很现实。 最近&#xff0c;人工智能AI技术火爆全网&#xff0c;而且它所表现出来的“超…