散列hash算法和加权随机java_一致性哈希算法

### 为什么要使用hash算法

> 在分布式系统中,为了提高吞吐量,集群是一个常见的手段,

> 为了保证访问集群中节点达到一个均衡的效果,就需要采用一些算法【轮询法】【随机法】【hash】【加权轮询】【加权随机】【最小连接数】

#### 以redis集群为例:

> 假设集群有4个节点,那么hash算法为:hash值 % 4,余数即为需要访问的节点。假设 hash值 % 4 = 2 那么就指向2号节点(0,1,2,3)。

#### hash算法的问题:

> 如果在4个节点的情况下,增加一个节点,那么算法为:hash值 % 5 那么,之前计算的结果就发生了变动,无法找到原来访问的节点了。

> 当大量的访问都找不到原来的节点,那么就会直接查数据库,造成缓存雪崩

### 一致性hash算法

#### 一致性hash算法介绍

> 一致性hash算法也是采用取模的方法,只是取模的分母不是节点数,而是固定的 2^32,这样所有的对象取模结果永远是一样的。

> hash取模结果就一定会在这个`hash环`上的一点,整个空间按顺时针方向组织。

![> ](https://box.kancloud.cn/60869aadcaef47548889936d2fc2af25_449x468.png)

#### 怎么找到对应的服务器

> 将服务器的ip或者主机名也通过 2^32进行取模,那么服务器也一定会落在这个hash环上,如图:

![> ](https://box.kancloud.cn/dc979ae5eedbac4021e913f97b55de00_714x727.png)

> 然后通过对象的hash结果,顺时针找,碰到的第一个服务器节点,就是分配的服务器,如图

> ObjectA-> NodeA ObjectB->NodeB ObjectC->NodeC ObjectD->NodeD

![](https://box.kancloud.cn/de30e10deba14b2a12414aede0fa3279_704x719.png)

#### 扩容,缩容是怎么操作的呢

> `扩容`

> 假设增加一个节点,那么这个节点到逆时针的节点之间的对象都会指向该新的服务器

![](https://box.kancloud.cn/c4efee6ff1040110a227a2c106b5ac25_696x722.png)

> `缩容`

> 假设移除一个节点,那么这个节点到沿着逆时针方向的那个节点之间的对象都会被指向到该移除的服务器的顺时针的下一个服务器

#### hash倾斜问题

> 原因:节点经过hash算法之后,并不会均衡的分布在hash环上,这就会导致这些节点分配的对象不均衡

![](https://box.kancloud.cn/917f1a2b56adbbda0d27da4b682ea51c_444x473.png)

> 解决办法:每个节点增加多个虚拟节点,这样就会尽量让节点均衡

![](https://box.kancloud.cn/3cd19e6f3eafe2fe5d3ee30a8fa713e9_720x731.png)


版权声明:本文为weixin_35123047原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。