常见分布式算法的介绍

背景知识:

  1. 哈希算法主要应用于缓存分布式系统。
  2. 分布式是指将一个整体拆成多个部分,由多个服务器来执行完成。注意与集群的区别,集群是将多个相同的整体部署在多个服务器上独立执行。
  3. 本文主要以key-value式缓存为例子讲解

1.节点取余:如果你的缓存服务器有3台,编号为0,1,2,节点取余的方式就是将key做哈希运算并将返回值与3(服务器个数)取余,根据值将value分配到相应编号的服务器中。例如:

例如我有6个key,分别是:1,2,3,4,5,6。根据上面的描述(假设hash函数返回值就是key的值),我们很容易计算出如下值的分布情况:
           0号服务器      1号服务器      2号服务器
key          3,6          1,4          2,5

注: key=3经过取余运算会被分配到0号服务器

但是需要注意的是,节点取余的容错性和扩展性不好,怎么理解呢,我们还是举例:

容错性:例如有一天我的2号服务器宕机了向外提供不了服务了,因此需要把它移除并对剩下的服务器重新编排,
紧接着取余算法也要相应发生改变,即与2取余得到的结果是:

       0号服务器      1号服务器
key     2,4,6       1,3,5


扩展性:例如由于我们的缓存服务器现在满足不了业务需求了,因此又增加一台服务器,同理取余算法相应也发生
了改变,即与4取余,得到的结果是:

       0号服务器       1号服务器      2号服务器       3号服务器

kay      4              1,5           2,6          3



我们都知道缓存服务,当key对应的值不存在时,会从源头获取数据(例如从mysql中),然后再存入缓存并返回
给客端,如果key对应的值存在即直接返回给客户端。基于这个原理,假设在三台服务器的时候,我们已经将1-6
个key对应的值设置在了相应的服务器中,这时候由于宕机了,服务器变成两台了按照上面分析的分布关系,我们
如果要获取2对应的值会被分配到0号服务器中去获取,但是0号服务器并没有存储(因为2对应的值在三台服务时
存储在了编号为2的服务器中),因此导致的结果就是缓存没有命中,即又要从源头中获取数据。
从上述的分析不难发现,节点取余这种方式只要服务器节点发生变化,缓存的命中率就会降低,因此不介意使用
如果硬要使用的话,建议扩充的节点是原来节点的两倍。

2.为了解决节点取余这种服务器数量一变更就导致大量缓存无法命中的问题,一致性哈希就出现了,一致性哈希说白了就是将整个哈希值设计成一个闭合的环状,并将服务器节点用哈希函数映射在这个环上,当有一个key过来了,利用相同的算法也映射在环上,有人可能会问了那么这个key到底是属于哪个服务器呢?根据key当前映射的位置顺时针走,遇到的第一个服务器就是key对应值所存储的服务器。具体可以查看下图(忽略图片左下角水印,粉红色圈就是key映射在环上的位置,白青色圈就是节点映射在换上的位置)

虽然一致性哈希解决了节点取余服务器数量变更导致大量缓存无法命中的问题,相对来说容错性和可扩展性也挺不错的,但是它仍然会导致小部分缓存数据无法命中的问题,这是需要注意的。(这也是为什么redis并没有使用一致性哈希算法而是使用虚拟槽这种替代方案,因为虚拟槽技术使得每一个节点管理的槽点是固定的,即使你增加了节点也是需要其他节点将槽点分配给新节点,新节点才有资格管理槽,因此就不会出现数据丢失的问题)。

猜你喜欢

转载自blog.csdn.net/wx145/article/details/82763422