菜单
开源

Grafana Mimir 哈希环

哈希环是一种分布式一致性哈希方案,被 Grafana Mimir 广泛用于分片和复制。

Grafana Mimir 中哈希环的工作原理

Grafana Mimir 中的哈希环用于以一致的方式在组件的多个副本之间分担工作,以便任何其他组件都能决定要与之通信的地址。需要分担的工作负载或数据首先被哈希,哈希结果用于确定哪个环成员拥有它。

Grafana Mimir 使用 fnv32a 哈希函数,该函数返回 32 位无符号整数,因此其值介于 0(2^32)-1 之间(包含边界)。该值称为 令牌,并用作数据的 ID。令牌确定数据在哈希环上的位置,具有确定性。这使得能够独立确定任何特定数据的权威所有者是哪个 Grafana Mimir 实例。

例如,序列(series)在ingester 之间进行分片。给定序列的令牌是通过对序列的所有标签和租户 ID 进行哈希计算得出的:结果是令牌空间内的 32 位无符号整数。拥有该序列的 ingester 是拥有包含该序列令牌的令牌范围的实例。

为了在集群中的可用实例之间划分可能的令牌集合 (2^32),给定 Grafana Mimir 组件(如 ingester)的所有运行实例都加入哈希环。哈希环是一种数据结构,它将令牌空间划分为多个范围,并将每个范围分配给特定的 Grafana Mimir 环成员。

启动时,实例生成随机令牌值,并将其注册到环中。每个实例注册的值决定了哪个实例拥有特定的令牌。一个令牌归注册了大于被查找令牌的最小值的实例所有(当达到 (2^32)-1) 时会绕回零)。

为了将数据复制到多个实例,Grafana Mimir 从数据的权威所有者开始,并顺时针遍历环来查找副本。数据会被复制到遍历环时找到的后续实例。

一个实际示例

为了更好地理解其工作原理,我们以四个 ingester 和一个介于 09 之间的令牌空间为例

  • Ingester #1 在环中注册的令牌是 2
  • Ingester #2 在环中注册的令牌是 4
  • Ingester #3 在环中注册的令牌是 6
  • Ingester #4 在环中注册的令牌是 9

Grafana Mimir 收到序列 {__name__="cpu_seconds_total",instance="1.1.1.1"} 的传入样本。它对序列的标签进行哈希计算,哈希函数的结果是令牌 3

为了找到哪个 ingester 拥有令牌 3,Grafana Mimir 在环中查找令牌 3,并找到注册的令牌值大于 3 的最小令牌的 ingester。注册令牌为 4 的 Ingester #2 是序列 {__name__="cpu_seconds_total",instance="1.1.1.1"} 的权威所有者。

Hash ring without replication

默认情况下,Grafana Mimir 将每个序列复制到三个 ingester。找到序列的权威所有者后,Grafana Mimir 继续顺时针遍历环,查找应复制该序列的其余两个实例。在接下来的示例中,该序列将被复制到 Ingester #3 和 Ingester #4 的实例。

Hash ring with replication

一致性哈希

哈希环保证了一致性哈希。

当一个实例被添加或从给定环中移除时,一致性哈希最大限度地减少了从一个实例移动到另一个实例的令牌数量。平均而言,需要移动到不同实例的令牌数量仅为 n/m,其中 n 是令牌的总数(32 位无符号整数),m 是环中注册的实例数量。

使用哈希环的组件

有几个 Grafana Mimir 组件需要哈希环。以下每个组件都构建一个独立的哈希环:

Grafana Mimir 实例之间如何共享哈希环

哈希环数据结构需要在 Grafana Mimir 实例之间共享。为了传播给定哈希环的更改,Grafana Mimir 使用键值存储。键值存储是必需的,并且可以为不同组件的哈希环独立配置。

有关更多信息,请参阅键值存储文档

使用哈希环构建的功能

Grafana Mimir 主要使用哈希环进行分片和复制。使用哈希环构建的功能包括:

  • 服务发现:实例可以通过查找环中注册的成员来发现彼此。
  • 心跳:实例周期性地向环发送心跳,表明它们正在运行。如果在一段时间内没有收到心跳,则认为实例不健康。
  • 区域感知复制:区域感知复制是将数据跨故障域进行复制,可以在 Grafana Mimir 中选择性启用。有关更多信息,请参阅配置区域感知复制
  • 洗牌分片:Grafana Mimir 选择性地支持在多租户集群中进行洗牌分片,以减少故障的影响范围,更好地隔离租户。有关更多信息,请参阅配置洗牌分片