目录
一、介绍
二、问题提出
三、朴素实施
四、一致性哈希
4.1 关闭服务器
4.2 添加新服务器
五、分布不均
5.1 虚拟节点
5.2 应用
六、结论
资源
一、介绍
我们生活在一个每天都会生成大量数据的世界里。在大公司中,几乎不可能将所有数据存储在单个服务器上。这就是为什么我们需要水平扩展,其中每个数据部分都存储在单独的服务器上。
与垂直扩展相反,我们可以简单地将所有数据存储在一个地方,而使用水平扩展,以能够快速访问不同服务器上的数据的方式组织存储至关重要。通过了解简单系统实现的性能缺点,我们将设计一个弹性系统来缓解上述问题。
在系统设计中,我们将使用的原则称为一致性哈希。
二、问题提出
假设我们有 n 个数据对象需要存储在 k 个不同的服务器上。服务器的配置可能会随时间而变化:
- 任何服务器都可以关闭;
- 可以将新服务器添加到系统中。
鉴于这些潜在的配置更改,我们必须设计一个系统,该系统可以在配置更改的情况下快速检索所需的数据块并在服务器之间传输数据。
三、朴素实施
朴素的实现包括基于哈希函数在不同服务器之间分配数据。例如,当我们需要向系统添加新的数据块时,我们将其密钥插入哈希函数中,该函数输出该块将属于的服务器编号。
基于哈希函数的数据分发。数据根据相应的哈希值存储在服务器上。
当我们需要从给定的密钥中检索信息时,我们会计算其哈希值,以找出与该密钥关联的信息存储在哪个服务器上。在实现这样的系统时,重要的是要确保哈希函数均匀分布数据,以便每个服务器存储的数据量大致相同。
在我们对其进行更改之前,此系统运行良好。例如,假设在上面的示例中,服务器 S3 已关闭:我们无法再访问其数据,并且不会添加将哈希到其存储桶的新数据。
每当任何服务器关闭时,其数据就无法再访问。
唯一可能的解决方案是再次将所有数据块重新分配到服务器上。既然我们现在有 k-1 个服务器,我们不应该忘记哈希函数中的余数必须减少 1。如果向系统添加了新服务器,则会出现类似的情况。
如果发生任何系统配置更改,则需要再次重新分发所有数据。
遗憾的是,数据重新分发是一项消耗资源的操作。在数据量大且配置频繁更改的情况下,此存储系统的效率会非常低。
四、一致性哈希
一致性哈希是上述系统的绝佳替代方案,在发生任何配置更改时具有更大的弹性。
一致性哈希不仅包括对数据进行哈希处理,还包括对服务器进行哈希处理。 数据键和服务器被哈希为同一组值 [0, n]。为了更容易理解和可视化,让我们想象所有的哈希值都位于一个环(或时钟)上。每个服务器都有自己的哈希范围。
服务器的哈希范围定义为位于哈希环上的所有哈希值的间隔,该哈希值位于服务器的哈希值之前和位于逆时针方向的另一个最近服务器的哈希值之后。
要确定某个密钥属于哪个服务器,我们需要从密钥的哈希值开始顺时针方向,直到到达与其中一个服务器对应的哈希值。该服务器将存储此密钥的数据。
哈希环示例。服务器 S1 的哈希范围以蓝色表示。
服务器的哈希值应按升序存储在其他位置,以便可以快速访问它们。使用二进制搜索,这提供了在 O(log S) 时间内查找存储给定密钥的服务器的能力(S 是服务器的数量)。
使用一致性哈希,可以在 O(log S) 时间内找到与给定密钥关联的服务器编号,其中 S 是服务器总数。
4.1 关闭服务器
如果任何服务器关闭,那么我们只需要删除该服务器的关联哈希值,并仅按顺时针方向将数据从该服务器传输到下一个服务器。与简单哈希相比,这是一致性哈希的一大优势,因为我们不再需要像以前那样重新分配所有数据。
从上面的示例中关闭服务器 S1 只需要传输以前存储在该服务器上的数据。
关闭 S1 后,服务器 S2 扩展了其哈希范围。
4.2 添加新服务器
如果需要向系统添加新的服务器,那么我们只需要将位于新服务器的哈希值和最近服务器的哈希值之间的哈希值关联的所有数据按逆时针方向传输即可。
将新服务器 S4 添加到系统。只有部分存储在 S0 上的数据必须传输到 S4。
添加 S4 后,它占用了以前属于 S0 的关联哈希值的一部分。
五、分布不均
虽然一致性哈希似乎对各种配置更改具有弹性,但可能会出现数据在服务器之间分布不均匀的时刻。
- 首先,这可能是由于所选的哈希函数而发生的。实际上,我们无法保证它会统一地为数据生成 key。因此,这可能会导致服务器具有非常不成比例的哈希范围长度的情况。
- 即使数据在给定的时刻均匀分布,随着各种配置的变化,它也可能很快发生急剧变化,再次变得不均匀。
分布不均匀程度越高,平均响应时间也会成比例地变长。
缓解此问题的一种可能方法是,当分布变得偏斜时,定期重新分配系统中的所有数据(可能使用另一个哈希函数)。虽然有时这可能是一种解决方案,但当拥有数百万或数十亿个数据对象时,它仍然不是最佳选择。
5.1 虚拟节点
虚拟节点是组合哈希的扩展,它使系统对不均匀的数据分布更具弹性。这个想法包括对每个服务器进行多次哈希处理(使用不同的哈希函数)。每个服务器的总哈希范围定义为与其所有键关联的哈希范围的联合。
与虚拟节点的一致性哈希。哈希环上的每种唯一颜色都对应于一个服务器。
- 关闭服务器意味着删除与该服务器关联的所有虚拟节点。来自该服务器的所有数据都将传输到其他多个服务器。
- 添加新服务器时,其虚拟节点的所有哈希值应通过之前用于其他服务器的哈希函数进行计算。
实际上,虚拟节点的数量通常比上面的例子多得多。
一方面,随着虚拟节点数量的增加,哈希范围平均变得更加一致。另一方面,执行与配置更改相关的标准操作需要更多时间。此外,还需要存储有关虚拟节点的其他元数据。
在大多数情况下,最好根据给定的问题、可用服务器的数量和数据数量来选择虚拟节点的数量。当难以估计一个好的数字时,建议调整此参数以找到完美的权衡。
5.2 应用
一致性哈希具有广泛的应用。大多数时候,它用于分布式应用程序,尤其是在许多服务器上存储大量数据的数据库。一些最流行的示例是:
- Apache Cassandra — 分布式 NoSQL 列数据库;
- Amazon Dynamo DB — 分布式 NoSQL 键值数据库;
- Discord — 视频和聊天应用程序。
六、结论
随着分布式系统的兴起,一致性哈希开始迅速普及。通过对频繁的配置更改具有弹性,它提供了一种简单而有效的解决方案来跨不同集群对数据进行分区。同时,虚拟数字的数量是一个重要参数,允许一致性哈希更适合大多数系统设置。
资源
- 一致性哈希 |维基百科