分布式算法之一致性 Hash 算法

news2024/11/28 6:36:36

tip:作为程序员一定学习编程之道,一定要对代码的编写有追求,不能实现就完事了。我们应该让自己写的代码更加优雅,即使这会费时费力。

💕💕 推荐:体系化学习Java(Java面试专题)

文章目录

  • 1、什么是一致性 Hash 算法
  • 2、一致性 Hash 算法详解
    • 2.1、Hash 环
    • 2.2、增删节点
    • 2.3、不平衡问题
    • 2.4、虚拟节点
  • 3、一致性 Hash 算法的应用

1、什么是一致性 Hash 算法

一致性哈希算法(Consistent Hashing)是一种分布式哈希算法,用于在分布式系统中解决节点动态变化带来的数据迁移问题。在一致性哈希算法中,哈希值的范围是一个环形空间,每个节点在环上占据一个位置,数据的哈希值也映射到环上,然后按照顺时针方向找到第一个节点,将数据存储在该节点上。当节点动态变化时,只需要对受影响的数据进行重新哈希,将其映射到新的节点上即可,无需对整个数据集进行重新分配。这种方式可以有效地减少数据迁移的开销,提高系统的可扩展性和稳定性。

在这里插入图片描述

2、一致性 Hash 算法详解

一致性哈希算法包含以下内容:

  1. 哈希环: 将数据的键值哈希到一个固定的范围内,通常是一个环形空间。

  2. 节点: 将节点的标识符哈希到环形空间上的一个位置,每个节点在环上占据一个位置。

  3. 数据分布: 将数据的键值哈希到环形空间上的一个位置,然后按照顺时针方向找到第一个节点,将数据存储在该节点上。

  4. 节点动态变化: 当节点动态变化时,只需要对受影响的数据进行重新哈希,将其映射到新的节点上即可,无需对整个数据集进行重新分配。

  5. 负载均衡: 由于节点在环上均匀分布,因此可以实现负载均衡,将数据均匀地分布在不同的节点上,避免单个节点的负载过高。

  6. 容错性: 由于节点在环上均匀分布,当某个节点发生故障时,只会影响其前一个节点到故障节点之间的数据,其他数据不会受到影响。

一致性哈希算法通过将数据的键值和节点的标识符映射到同一个环形空间上,实现了数据分布和负载均衡,并且具有良好的容错性和可扩展性。

2.1、Hash 环

哈希环(Hash Ring)是一种数据结构,通常用于实现一致性哈希算法。哈希环是一个环形结构,其中每个节点表示一个哈希值,节点按照哈希值的大小顺序排列,形成一个环。当需要将数据映射到节点时,可以通过哈希函数计算数据的哈希值,然后在哈希环上找到第一个大于等于该哈希值的节点,将数据映射到该节点上。

以下是自己手写一个 Hash 环的代码:

package com.pany.camp.algorithm;

import java.util.*;

/**
 *
 * @description:  Hash 环
 * @copyright: @Copyright (c) 2022
 * @company: Aiocloud
 * @author: pany
 * @version: 1.0.0
 * @createTime: 2023-06-09 12:58
 */
public class HashRing<T> {

    private final TreeMap<Integer, T> ring = new TreeMap<>();
    private final HashFunction hashFunction;

    public HashRing(Collection<T> nodes, HashFunction hashFunction) {
        this.hashFunction = hashFunction;
        for (T node : nodes) {
            addNode(node);
        }
    }

    public void addNode(T node) {
        for (int i = 0; i < 3; i++) { // 每个节点在哈希环上占据 3 个位置,增加数据的分布均匀性
            int hash = hashFunction.hash(node.toString() + i);
            ring.put(hash, node);
        }
    }

    public void removeNode(T node) {
        for (int i = 0; i < 3; i++) {
            int hash = hashFunction.hash(node.toString() + i);
            ring.remove(hash);
        }
    }

    public T getNode(String key) {
        if (ring.isEmpty()) {
            return null;
        }
        int hash = hashFunction.hash(key);
        if (!ring.containsKey(hash)) {
            Map.Entry<Integer, T> entry = ring.ceilingEntry(hash);
            if (entry == null) {
                entry = ring.firstEntry();
            }
            return entry.getValue();
        }
        return ring.get(hash);
    }

    public interface HashFunction {
        int hash(String key);
    }

}

根据 Hash 环,举个一个负载均衡的例子。LoadBalancer 类封装了一个 HashRing 对象,用于存储服务器节点。构造函数中需要传入服务器集合,getServer 方法用于将请求映射到服务器节点上。在 main 方法中,创建一个 LoadBalancer 对象,然后循环发送 10 个请求,将请求映射到不同的服务器上。由于 HashRing 实现了一致性哈希算法,因此可以保证请求的负载均衡性。

package com.pany.camp.algorithm;

import java.util.*;

/**
 *
 * @description:  负载均衡
 * @copyright: @Copyright (c) 2022 
 * @company: Aiocloud
 * @author: pany
 * @version: 1.0.0 
 * @createTime: 2023-06-09 12:58
 */
public class LoadBalancer {

    private final HashRing<String> serverRing;

    public LoadBalancer(Collection<String> servers) {
        serverRing = new HashRing<>(servers, key -> Math.abs(key.hashCode()));
    }

    public String getServer(String request) {
        return serverRing.getNode(request);
    }

    public static void main(String[] args) {
        List<String> servers = Arrays.asList("server1", "server2", "server3");
        LoadBalancer lb = new LoadBalancer(servers);
        for (int i = 0; i < 10; i++) {
            String request = "request" + i;
            String server = lb.getServer(request);
            System.out.println("Request " + request + " is sent to server " + server);
        }
    }
}

2.2、增删节点

根据上面的 HashRing 解释一致性哈希算法的增删节点逻辑:

  1. 添加节点
    添加节点时,需要计算节点的哈希值,并将其添加到哈希环上。在 HashRing 中,可以通过 addNode 方法来添加节点。该方法首先计算节点的哈希值,然后将其添加到哈希环上。如果节点已经存在,则不会进行任何操作。通常情况下,每个节点会在哈希环上占据多个位置,以增加数据的分布均匀性。在 HashRing 中,可以通过 replicaCount 参数来指定每个节点在哈希环上占据的位置数。

  2. 删除节点
    删除节点时,需要将节点从哈希环上删除。在 HashRing 中,可以通过 removeNode 方法来删除节点。该方法首先计算节点的哈希值,然后将其从哈希环上删除。如果节点不存在,则不会进行任何操作。

  3. 查找节点
    查找节点时,需要先计算数据的哈希值,然后在哈希环上找到第一个大于等于该哈希值的节点,将数据映射到该节点上。如果不存在该节点,则取哈希环上最小的节点。在 HashRing 中,可以通过 getNode 方法来查找节点。该方法首先计算数据的哈希值,然后在哈希环上查找第一个大于等于该哈希值的节点。如果找不到该节点,则返回哈希环上最小的节点。

需要注意的是,当添加或删除节点时,可能会导致某些数据映射到新的节点上,从而需要重新分配数据。为了减少数据的迁移量,可以使用虚拟节点(也称为虚拟哈希环)来增加节点数量,从而使得每个节点在哈希环上占据更多的位置。在 HashRing 中,可以通过虚拟节点来实现。具体来说,可以为每个节点分配多个虚拟节点,然后将虚拟节点添加到哈希环上。这样,当添加或删除节点时,只需要重新分配少量的数据即可。

2.3、不平衡问题

一致性哈希算法的不平衡问题主要是由于节点数量过少或者节点分布不均匀所导致的。当节点数量较少时,可能会出现节点分布不均匀的情况,从而导致某些节点负载过重,而其他节点负载较轻。当节点分布不均匀时,可能会出现数据倾斜的情况,从而导致某些节点存储的数据过多,而其他节点存储的数据过少。

为了解决这个问题,可以采取以下措施:

  1. 增加节点数量
    增加节点数量可以增加哈希环上的节点数量,从而使得数据分布更加均匀。通常情况下,节点数量应该足够多,以保证数据分布的均匀性。

  2. 使用虚拟节点
    使用虚拟节点可以增加节点数量,从而使得每个节点在哈希环上占据更多的位置。这样可以减少数据的倾斜程度,从而提高负载均衡性。在 HashRing 中,可以通过虚拟节点来实现。

  3. 负载均衡策略

可以采用更加智能的负载均衡策略,例如基于节点负载情况的动态负载均衡策略。这样可以使得节点的负载更加均衡,从而提高系统的性能和可靠性。

2.4、虚拟节点

在一致性哈希算法中,虚拟节点是指将一个物理节点映射到多个虚拟节点上的技术。通过将一个物理节点映射到多个虚拟节点上,可以增加节点在哈希环上的占据位置,从而使得数据分布更加均匀。虚拟节点的数量可以根据需要进行调整,通常情况下,虚拟节点的数量要足够多,以保证数据分布的均匀性。

例如,在一个有 3 个物理节点的哈希环中,每个物理节点可以映射到 5 个虚拟节点上,这样总共就会有 15 个虚拟节点。当需要将一个数据存储到哈希环上时,首先需要计算该数据的哈希值,然后将其映射到离其最近的虚拟节点上。由于每个物理节点在哈希环上占据了多个虚拟节点的位置,因此可以使得数据分布更加均匀,从而提高负载均衡性。

虚拟节点的实现可以通过在哈希值的计算过程中,将物理节点和虚拟节点一起计算。在 HashRing 中,可以通过传递一个计算虚拟节点数量的函数来实现虚拟节点的功能。具体而言,计算虚拟节点数量的函数可以将物理节点和虚拟节点的编号拼接在一起,然后计算它们的哈希值。这样就可以将一个物理节点映射到多个虚拟节点上。

3、一致性 Hash 算法的应用

一致性哈希算法是一种常用的分布式算法,它在很多分布式系统和应用中得到了广泛的应用,下面介绍一些常见的应用场景:

  1. 分布式缓存
    一致性哈希算法被广泛应用于分布式缓存系统中,如 Memcached、Redis 等。在分布式缓存系统中,数据通常会被分散到多个缓存节点上,而一致性哈希算法可以有效地将数据均匀地分布到各个缓存节点上,从而提高缓存系统的性能和可扩展性。

  2. 负载均衡
    一致性哈希算法也可以用于负载均衡系统中,如 HTTP 负载均衡、DNS 负载均衡等。在负载均衡系统中,一致性哈希算法可
    以将请求均匀地分发到多个服务器上,从而提高系统的负载均衡性和可扩展性。

  3. 分布式数据库
    一致性哈希算法也可以用于分布式数据库系统中,如 Cassandra、MongoDB 等。在分布式数据库系统中,数据通常会被分散到多个节点上,而一致性哈希算法可以将数据均匀地分布到各个节点上,从而提高数据的可用性和可扩展性。

  4. 分布式文件系统
    一致性哈希算法也可以用于分布式文件系统中,如 HDFS、GlusterFS 等。在分布式文件系统中,文件通常会被分散到多个
    节点上,而一致性哈希算法可以将文件均匀地分布到各个节点上,从而提高文件系统的性能和可扩展性。

总之,一致性哈希算法是一种非常实用的分布式算法,可以在很多分布式系统和应用中发挥重要作用。

💕💕 本文由激流原创,首发于CSDN博客,博客主页 https://blog.csdn.net/qq_37967783?spm=1010.2135.3001.5421
💕💕喜欢的话记得点赞收藏啊

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

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

相关文章

第35步 机器学习实战DLC:不平衡数据处理(下)

失踪人口回归的第二期&#xff0c;继续说一说用PSM处理不平衡数据。 一、啥叫PSM PSM全称为Propensity Score Matching&#xff0c;翻译过来就是倾向匹配得分&#xff0c;为了省流&#xff0c;让小Chart介绍一下&#xff1a; 放到我们的数据就是&#xff1a;根据某个特征&…

架构师需要看透公司的用户心智定位

一个架构师要站在用户的角度去思考架构的规划和设计。把注意力放在用户身上&#xff0c;已经有无数案例证明是可以带来重大商业和技术突破的。 很多创业公司&#xff0c;从初创到倒闭&#xff0c;都没搞清楚自己的目标人群和心智。如果一个公司&#xff0c;能锁定目标人群及其…

7个最佳WooCommerce跨境电商社交媒体插件

在互联的早期&#xff0c;您通常可以将产品直接放到网上并出售。但在今天你必须进行营销和做广告。如果没有包括社交媒体在内的可持续营销策略&#xff0c;您的商店可能会被忽视。值得高兴的是&#xff0c;有很多 WooCommerce跨境电商社交媒体插件可以用来传播信息&#xff0c;…

【CMake 入门与进阶(5)】 CMakeLists.txt 语法规则基础及部分常用指令-续(附使用代码)

project project命令用于设置工程名称&#xff1a; # 设置工程名称为 HELLO project(HELLO)执行这个之后会引入两个变量&#xff1a;HELLO_SOURCE_DIR 和 HELLO_BINARY_DIR&#xff0c;注意这两个变量名的前缀就是工程名称&#xff0c;HELLO_SOURCE_DIR 变量指的是 HELLO 工程…

华为推出首款全栈自主数据库 GaussDB,你怎么看?

鸿蒙套壳&#xff0c;鸿蒙套壳完了ERP套&#xff0c;ERP套壳&#xff0c;ERP套壳完了数据库套壳&#xff0c;数据库套壳完了…… 犹记得GaussDB之前一直宣传是基于PostgreSQL研发而来&#xff0c;不知道今天为啥摇身一变为首款全栈自主分布式数据库了。 基于开源研发改不恶心。…

智能设备管理系统

传统设备实施管理难点&#xff1a; 1、日常工作繁琐&#xff0c;手动纸质记录和 Excel 管理设备数据麻烦&#xff0c;后期难以汇总管理&#xff0c;且数据易丢失。 2、需核对设备巡检、保养、故障维修记录&#xff0c;手动更新设备状态和最近维修时间等。 3、无法实时获取设备最…

大学生网络工程想走网络安全方向该怎么规划?

明确需求,确定方向 网络安全 网络安全 是一个很广的概念&#xff0c;涉及的岗位也是非常多的&#xff0c;有安全服务、安全运维、渗透测试、web安全、安全开发、安全售前等等。可以看看下面每个岗位的要求与自身兴趣能力匹配度再决定最适合自己的方向。 渗透测试/Web安全工程师…

开启人机协作新时代:协作机器人的应用与展望

原创 | 文 BFT机器人 01 蓄势待发&#xff0c;产业变革新引擎 近年来&#xff0c;在政策扶持、资本助推和技术创新的共同作用下&#xff0c;产业迎来发展黄金期。日前&#xff0c;各行各业正经历产业智能化转型&#xff0c;机器人市场规模不断扩大&#xff0c;发展前景广阔&…

万宾建筑结构健康监测系统方案

建筑结构健康监测是现代建筑工程领域的重要措施之一。通过实时监测和评估建筑物的结构状态&#xff0c;可以及早发现潜在的问题&#xff0c;保障建筑物的安全性和稳定性。 随着城市化进程的加速和建筑规模的扩大&#xff0c;建筑结构的安全性和稳定性越来越受到关注。然而&…

chatgpt赋能python:Python快速打开:如何提高Python执行速度

Python 快速打开&#xff1a;如何提高 Python 执行速度 介绍 Python 是一种解释型语言&#xff0c;由于其简洁易读&#xff0c;广泛用于数据科学、机器学习、Web 开发等领域。然而&#xff0c;它的执行速度相对较慢&#xff0c;这通常是由于其解释器中面临的硬件资源限制以及…

如何查看docker下的mysql版本

进入运行的mysql的容器 docker exec -it mysqlserver bash 标红的位置可以是我们运行的别名&#xff0c;也可以为id 我们想连接mysql服务时报错了 我们看下配置文件 cat /etc/my.cnf 可以看到配置文件的sock文件位置并不在/var/lib/mysql文件夹中 这里又两种办法 1.直接修改…

JVM--方法区元空间

前言 本篇对java的JVM线程共享内存中的方法区进行系统性的讲解。 1、方法区&元空间概念 方法区是《Java虚拟机规范》中规定的一个内存区域&#xff0c;它用于存储已被虚拟机加载的类型信息、常量、静态变量、即时编译器编译后的代码缓存等。 元空间是方法区的实现。方法…

python基础----09-----类、对象、魔法方法、封装、继承、类型注解、多态、数据分析案例

一 初识对象 说白了就是类的实例化&#xff0c;类是一个抽象层的定义。 例如下面class Student就是定义的一个类&#xff0c;它是抽象层&#xff0c;然后stu_1 Student()&#xff0c;我们根据类创建了一个对象&#xff0c;就是对类的实例化&#xff0c;这个实例化对象我们是可…

paas云底座-数字化转型,你真的了解么

云底座是什么&#xff1f; 如图 底座其实就是一个基础打个比方&#xff1a; 把底座看成一块土地&#xff0c;我们在这块土地上可以盖楼房&#xff0c;可以挖一个游泳池&#xff0c;可以开一家饭店 也就是说我们这块土地可以开发很多东西言归正传 云底座其实就是数字化转型的“底…

【快速幂】-迭代法:详解

何为快速幂&#xff1f; 我们经常会计算&#xff1a;。STL中有自带的pow函数&#xff0c;如果当n很大的时候&#xff0c;那么一定会TLE。 因此&#xff0c;我们需要另一种求值的方法&#xff1a;快速幂&#xff01; 快速幂有两种做法&#xff1a;1&#xff1a;递归 2…

谷歌云 | 宣布跨云互连:无缝连接到您的所有云

【本文由Cloud Ace整理发布&#xff0c;Cloud Ace 是谷歌云全球战略合作伙伴&#xff0c;拥有 300 多名工程师&#xff0c;也是谷歌最高级别合作伙伴&#xff0c;多次获得 Google Cloud 合作伙伴奖。作为谷歌托管服务商&#xff0c;我们提供谷歌云、谷歌地图、谷歌办公套件、谷…

1 软件测试基本概念

文章目录 课程目标1. 入门前的7个基础问题2. 软件测试基本概念2.1 需求的概念2.1.1需求的基本概念2.1.2 从软件测试人员角度看需求2.1.3 为什么需求对软件测试人员如此重要&#xff1f;2.1.4 如何才可以深入理解被测试软件的需求 2.2 bug的概念(了解)2.3测试用例的概念2.3.1 概…

AI读心术

近期&#xff0c;德克萨斯大学奥斯汀分校的神经科学家们展开了一场「AI」实验&#xff0c;利用人工智能聊天机器人ChatGPT&#xff0c;将大脑活动转化为文字信息。 参与实验的志愿者&#xff0c;在进行长达20小时的「训练」后&#xff0c;成功被「AI」识别出正在进行的活动。按…

portraiture宿主插件最新v4中文版本下载及使用教程

自拍怎么可以不修图呢&#xff1f;如果要修图的话&#xff0c;磨皮就是其中非常重要的一环。皮肤看起来细腻光滑了&#xff0c;整个人的颜值都会瞬间拉高。下面就让我们介绍一下磨皮用什么软件好用&#xff0c;什么软件可以手动磨皮的相关内容。portraiture是ps人像修图中常用的…

喜报!恭喜知了堂学员成功通过CISP-PTE证书考试

有人说&#xff0c;大学可以不谈恋爱&#xff0c;但一定要考证。 考证&#xff0c;是大学校园生活的关键一环。充分利用在校时间为后期就业提前储备优势&#xff0c;毕业后如果从事IT领域&#xff0c;证书就是一个高含金量的专业认证&#xff0c;尤其是网络安全行业&#xff0…