深入浅出一致性哈希

发布时间 2023-12-29 10:54:15作者: fix-bugs

哈希是什么

哈希又称散列,是一种计算数据指纹的方法。
哈希函数把消息或数据压缩成摘要,使得数据量变小,将数据的格式固定下来

业务场景

常见的业务场景;网站用户请求后,为了性能一般都会加一层缓存。
image
缓存有多个节点,每个节点存储了不同数据。
获取数据,先根据数据取模(哈希)找到缓存节点,如果命中缓存则直接返回结果。否则,请求DB,再缓存,再返回结果。

取模算法:hash(data)=data mod nodeNum,比如请求数据是100,有3个节点,定位在哪个节点,使用 100%3=1 来定位到 index=1 的节点

image
问题:比如系统负载能力不足,再加个缓存节点,但是发现基本上所有数据取余的结果会发生变化
image
新增节点后,请求到缓存服务节点0,但是节点0没有缓存数据,又去请求DB。如果大量请求过来,大部分都去请求DB,造成DB的压力,这样也失去的增加缓存服务的意义了。

一致性哈希

摘自维基百科 https://zh.wikipedia.org/wiki/一致哈希

一致哈希将每个对象映射到圆环边上的一个点,系统再将可用的节点机器映射到圆环的不同位置。查找某个对象对应的机器时,需要用一致哈希算法计算得到对象对应圆环边上位置,沿着圆环边上查找直到遇到某个节点机器,这台机器即为对象应该保存的位置。 当删除一台节点机器时,这台机器上保存的所有对象都要移动到下一台机器。添加一台机器到圆环边上某个点时,这个点的下一台机器需要将这个节点前对应的对象移动到新机器上。 更改对象在节点机器上的分布可以通过调整节点机器的位置来实现

比如有3个节点,将节点信息hash后,找到圆环的位置
image

有请求数据时,对数据也做hash,找到圆环位置。那么从数据data位置开始,按顺时针寻址到的第一个节点就是要请求的节点
image

当有新节点 D 加进来后,D的位置如果在B前面,那么将B的数据迁移到D,相同的数据data计算节点是D。
这样的好处是,不用所有节点都做数据迁移,只需要迁移一个或少量数据
image

同样道理,当节点B下线时,将B的数据迁移到节点C
image

节点不均衡问题

一致性哈希可以解决数据大量移动的问题。但是可能存在这样的情况:大量请求的数据经过hash计算,都寻址到某一个节点,这样这个节点会面临很大压力,而其他节点很空闲资源浪费
image

这时候,又有人想出来了虚拟节点(不得不说,人类这个脑子是真的聪明)
将每个节点都分配多个虚拟节点,分布在圆环上,这样圆环上的节点就很均匀了
image

nginx中也有一致性hash的使用

https://www.nginx.com/resources/wiki/modules/consistent_hash/

upstream somestream {
  consistent_hash $request_uri;
  server 10.50.1.3:11211;
  server 10.50.1.4:11211;
  server 10.50.1.5:11211;
}

// ...
server {
  listen       80;
  server_name  localhost;

  location / {
    default_type text/html;
    set $memcached_key $request_uri;
    memcached_pass somestream;
    error_page      500 404 405 = @fallback;
  }
}