一致性HASH算法笔记

一致性HASH算法解决了普通HASH算法在分布式环境中数据迁移导致的问题,通过在哈希环上分布服务器节点,确保增删节点时数据迁移影响最小。文章介绍了Hash算法的类型和在分布式环境中的应用,并详细讲解了一致性HASH算法的工作原理,包括不含虚拟节点和含有虚拟节点的实现方式,旨在实现负载均衡和高可用性。
摘要由CSDN通过智能技术生成

title: 一致性HASH算法笔记
comments: true
toc: true
categories:

  • 分布式方案
    tags:
  • 一致性HASH
  • HASH算法
    date: 2020-12-29 02:09:47

​ 散列算法(Hash Algorithm),又称哈希算法,杂凑算法,是一种从任意文件中创造小的数字「指纹」的方法。也可以理解为空间映射函数,是从一个非常大的取值空间映射到一个非常小的取值空间,由于不是一对一的映射,Hash 函数转换后不可逆,意思是不可能通过逆操作和 Hash 值还原出原始的值。在互联网环境中有非对称加密、文件签名、Hash表寻址算法等应用。

Hash算法类型

直接寻址法:按照该值作为三列地址进行查找。

除留余数法(数据取模法):对该值按照散列表的长度来取余。

处理Hash冲突时的方法:

​ 开放寻址法:冲突后向前或者向后寻找空位作为当前地址。

​ 再散列法:准备多个散列函数,冲突后使用其他散列函数计算。

​ 拉链法:冲突后,将冲突的数据放到一个链表中。

Hash算法在分布式环境中的应用

  • 请求的负载均衡(如nginx的ip_hash策略)

    Nginx负载均衡的经典应用就是通过ip地址或者sessionid进行计算哈希值,哈希值与服务器数量进行取模运算,得到的值就是当前请求应该被路由到的服务器编号,如此,同一个客户端ip发送过来的请求就可以路由到同一个目标服务器,实现会话粘滞。

    如果不使用hash算法,就需要非常维护非常大的映射表,造成内存浪费,且服务器上下线后不利于维护。

  • 分布式存储

    比如Redis集群模式下,数据应该存储在哪个redis应用里呢?通过Hash算法就可以解决这个问题。

普通HASH算法带来的数据迁移问题

​ 在普通HASH算法下,,如果hash表扩容/缩容,所有的数据均需要重新计算一遍来确定寻址位置。在大量数据的环境下,这会带来很多问题。比如Nginx下的ip_hash负载均衡策略,它的目的是将同一个客户端的请求路由到同一台服务器上,当服务器扩容或者缩容时,使用普通hash算法则使得所有客户端重新计算路由的服务器编号,大量的客户端session失效,这在互联网环境下是难以接受的。

一致性HASH算法

​ 有一条直线,直线开头和结尾分别定为为1和2的32次方减1,这相当于一个地址。

一致性Hash直线

​ 对于这样一条线,弯过来构成一个圆环形成闭环,这样的一个圆环称为hash环。

一致性hash环

​ 我们把服务器的ip或者主机名求hash值然后对应到hash环上,那么针对客户端用户,也根据它的ip进行hash求值,对应到环上某个位置,然后如何确定一个客户端路由到哪个服务器处理呢?按照顺时针方向找最近的服务器节点。比如服务器A在hash环上对应的值为100,服务器B在hash环上对应的值为200,那么经过hash计算后值为大于100小于200的均路由到服务器B上。

  1. 当服务下线时

    ​ 会按照顺时针将请求路由至下一个服务器。

  2. 当服务上线时

    ​ 会将当前节点逆时针至上一台服务器的请求路由至本服务器。

总的来说Hash环按照服务器的数量划分成了不同的段,每台服务器负责一段,增减服务器均只影响部分数据,具有良好的容错性和扩展性。

​ 但分段也造成了数据倾斜问题,即负载不均衡的问题,有的服务器器不堪重负,有的服务器资源闲置浪费。这就需要我们尽可能的使服务器分布均衡。当我们的服务器节点较少时,可以采用填充虚拟节点的方式来平衡分段。具体的做法是给每个虚拟节点分配一个真实的物理节点,当请求到虚拟节点时,路由至附带的真实节点。

一致性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 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值