2-2-1 一致性Hash问题及解决方案

前言、分布式和集群

分布式和集群的概念

分布式和集群是不⼀样的,分布式⼀定是集群,但是集群不⼀定是分布式(因为集群就是多个实例⼀起⼯作,分布式将⼀个系统拆分之后那就是多个实例;集群并不⼀定是分布式,因为复制型的集群不是拆分⽽是复制)

在这里插入图片描述

一、一致性Hash算法

1.1、一致性Hash算法之Hash回顾溯源

Hash算法,⽐如说在安全加密领域MD5、SHA等加密算法,在数据存储和查找⽅⾯有Hash表等, 以上都应⽤到了Hash算法。

为什么需要使⽤Hash?
Hash算法较多的应⽤在数据存储和查找领域,最经典的就是Hash表,它的查询效率⾮常之⾼,其中的
哈希算法如果设计的⽐较ok的话,那么Hash表的数据查询时间复杂度可以接近于O(1)

1.1.1 案例
  • 案例:提供⼀组数据 1,5,7,6,3,4,8,对这组数据进⾏存储,然后随便给定⼀个数n,请你判断n是否存在于刚才的数据集中

  • 顺序查找法

    list:List[1,5,7,6,3,4,8]
    // 通过循环判断来实现
    for(int element: list) {
    if(element == n) {
    如果相等,说明n存在于数据集中
    }}
    以上这种⽅法叫做顺序查找法 :这种⽅式我们是通过循环来完成,⽐较原始,效率也不⾼

  • ⼆分查找

    排序之后折半查找,相对于顺序查找法会提⾼⼀些效率,但是效率也并不是特别好

  • 直接寻址法
    在这里插入图片描述

    定义⼀个数组,数组⻓度⼤于等于数据集⻓度,此处⻓度为9,数据1就存储在下标为1的位置,3就存储在下标为3的元素位置,,,依次类推。
    这个时候,我想看下5存在与否,只需要判断list.get(5) array[5] 是否为空,如果为空,代表5不存在于数据集,如果不为空代表5在数据集当中,通过⼀次查找就达到了⽬的,时间复杂度为O(1)。这种⽅式叫做“直接寻址法”:直接把数据和数组的下标绑定到⼀起,查找的时候,直接array[n]就取出了数据

    优点:速度快,⼀次查找得到结果
    缺点:
    1)浪费空间,⽐如 1,5,7,6,3,4,8,12306 ,最⼤值12306 ,按照上述⽅式需要定义⼀个⽐如⻓度为12307的数组,但是只存储零星的⼏个数据,其他位置空间都浪费着
    2)数据如:1,5,7,6,3,4,8,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2最⼤值12,⽐如开辟13个空间,存储不了这么多内容

  • 拉链法

    现在,换⼀种设计,如果数据是3,5,7,12306,⼀共4个数据,我们开辟任意个空间,⽐如5个,那么具体数据存储到哪个位置呢,我们可以对数据进⾏求模(对空间位置数5),根据求模余数确定存储位置的下标,⽐如3%5=3,就可以把3这个数据放到下标为3的位置上,12306%5=1,就把12306这个数据存储到下标为1的位置上

在这里插入图片描述

上⾯对数据求模 (数据%空间位置数) 他就是⼀个hash算法,只不过这是⼀种⽐较普通⼜简单的hash算法,这种构造Hash算法的⽅式叫做除留余数法

如果数据是1,6,7,8,把这4个数据存储到上⾯的数组中

在这里插入图片描述
拉链法:数据⻓度定义好了,怎么存储更多内容呢,算好Hash值,在数组元素存储位置放了⼀个链表

在这里插入图片描述
如果Hash算法设计的⽐较好的话,那么查询效率会更接近于O(1),如果Hash算法设计的⽐较low,那么查询效率就会很低了

在这里插入图片描述
所以,Hash表的查询效率⾼不⾼取决于Hash算法,hash算法能够让数据平均分布,既能够节省空间⼜
能提⾼查询效率。Hash算法的研究是很深的⼀⻔学问,⽐较复杂,⻓久以来,Hash表内部的Hash算法
也⼀直在更新,很多数学家也在研究。
除留余数法 3%5
线性构造Hash算法
直接寻址法也是⼀种构造Hash的⽅式,只不过更简单,表达式:H(key)=key
⽐如H(key)=a*key + b(a,b是常量)
hashcode其实也是通过⼀个Hash算法得来的

1.2、一致性Hash算法之负载均衡应用场景

Hash算法在分布式集群架构中的应⽤场景
Hash算法在很多分布式集群产品中都有应⽤,⽐如分布式集群架构Redis、Hadoop、ElasticSearch,
Mysql分库分表,Nginx负载均衡等
主要的应⽤场景归纳起来两个

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

在这里插入图片描述

Nginx的IP_hash策略可以在客户端ip不变的情况下,将其发出的请求始终路由到同⼀个⽬标服务
器上,实现会话粘滞,避免处理session共享问题
如果没有IP_hash策略,那么如何实现会话粘滞?
可以维护⼀张映射表,存储客户端IP或者sessionid与具体⽬标服务器的映射关系
<ip,tomcat1>
缺点
1)那么,在客户端很多的情况下,映射表⾮常⼤,浪费内存空间
2)客户端上下线,⽬标服务器上下线,都会导致重新维护映射表,映射表维护成本很⼤

1.2.2、Nginx的ip_hash策略C语言源码核心部分浏览
1.2.3、一致性Hash算法之分布式存储应用场景

如果使⽤哈希算法,事情就简单很多,我们可以对ip地址或者sessionid进⾏计算哈希值,哈希值与服务
器数量进⾏取模运算,得到的值就是当前请求应该被路由到的服务器编号,如此,同⼀个客户端ip发送
过来的请求就可以路由到同⼀个⽬标服务器,实现会话粘滞。

以分布式内存数据库Redis为例,集群中有redis1,redis2,redis3 三台Redis服务器
那么,在进⾏数据存储时,<key1,value1>数据存储到哪个服务器当中呢?针对key进⾏hash处理
hash(key1)%3=index, 使⽤余数index锁定存储的具体服务器节点

二、手写算法
2.1、普通Hash算法存在的问题

在这里插入图片描述

2.2、一致性Hash算法原理

哈希环

在这里插入图片描述

2.3 一致性Hash算法缩容扩容分析

在这里插入图片描述
在这里插入图片描述

2.4、 一致性Hash算法+虚拟节点方案

1)如前所述,每⼀台服务器负责⼀段,⼀致性哈希算法对于节点的增减都只需重定位环空间中的⼀⼩
部分数据,具有较好的容错性和可扩展性。
但是,⼀致性哈希算法在服务节点太少时,容易因为节点分部不均匀⽽造成数据倾斜问题。例如系统中
只有两台服务器,其环分布如下,节点2只能负责⾮常⼩的⼀段,⼤量的客户端
请求落在了节点1上,这就是数据(请求)倾斜问题
2)为了解决这种数据倾斜问题,⼀致性哈希算法引⼊了虚拟节点机制,即对每⼀个服务节点计算多个
哈希,每个计算结果位置都放置⼀个此服务节点,称为虚拟节点。
具体做法可以在服务器ip或主机名的后⾯增加编号来实现。⽐如,可以为每台服务器计算三个虚拟节
点,于是可以分别计算 “节点1的ip#1”、“节点1的ip#2”、“节点1的ip#3”、“节点2的ip#1”、“节点2的
ip#2”、“节点2的ip#3”的哈希值,于是形成六个虚拟节点,当客户端被路由到虚拟节点的时候其实是被
路由到该虚拟节点所对应的真实节点

在这里插入图片描述

2.5、手写实现Hash算法之普通Hash算法实现

在这里插入图片描述

2.6、手写实现Hash算法之一致性哈希算法实现

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.7、手写实现Hash算法之一致性哈希算法含虚拟节点方案实现

三、 Nginx配置一致性Hash负载均衡策略

在这里插入图片描述

在这里插入图片描述

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值