菜单
开源

Pyroscope 哈希环

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

哈希环在 Pyroscope 中的工作原理

Pyroscope 中的哈希环用于跨组件的多个副本一致地共享工作,以便其他组件可以确定要与之通信的地址。要共享的工作负载或数据首先进行哈希计算,然后使用哈希结果查找哪个环成员拥有它。

Pyroscope 使用 fnv32a 哈希函数,该函数返回 32 位无符号整数,因此其值可以在 0(2^32)-1(包含)之间。此值称为令牌(token),用作数据的 ID。令牌决定了数据在哈希环上的确定性位置。这允许独立确定 Pyroscope 的哪个实例是任何特定数据的权威所有者。

例如,性能分析数据被分片到多个ingester 中。给定性能分析数据的令牌是通过对该性能分析数据的所有标签和租户 ID 进行哈希计算得出的:其结果是一个在令牌空间内的无符号 32 位整数。拥有该系列性能分析数据的 ingester 是拥有令牌范围(包括该性能分析数据令牌)的实例。

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

启动时,实例会生成随机令牌值,并将其注册到环中。每个实例注册的值决定了哪个实例拥有给定令牌。令牌由注册了比要查找的令牌值更高且最小的实例拥有(当达到 (2^32)-1) 时会环绕到零)。

为了在多个实例之间复制数据,Pyroscope 从数据的权威所有者开始,沿着环顺时针查找副本。数据会被复制到在环上找到的后续实例。

一个实际示例

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

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

Pyroscope 接收到一个传入的性能分析数据,其标签为 {__name__="process_cpu", instance="1.1.1.1"}。它对性能分析数据的标签进行哈希计算,哈希函数的结果是令牌 3

为了找到哪个 ingester 拥有令牌 3,Pyroscope 在环中查找令牌 3,并找到注册了比 3 大且最小的令牌的 ingester。注册令牌 4 的 Ingester #2 是该性能分析数据 {__name__="process_cpu",instance="1.1.1.1"} 的权威所有者。

Hash ring without replication

当复制设置为 3 时,Pyroscope 会将每个性能分析数据复制到三个 ingester。在找到该性能分析数据的权威所有者后,Pyroscope 继续沿着环顺时针查找应复制该性能分析数据的另外两个实例。在接下来的示例中,该性能分析数据被复制到 Ingester #3 和 Ingester #4 的实例中。

Hash ring with replication

一致性哈希

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

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

使用哈希环的组件

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

哈希环如何在 Pyroscope 实例之间共享

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

有关更多信息,请参阅 memberlist 文档

使用哈希环构建的功能

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

  • 服务发现:实例可以通过查找环中注册的信息来发现彼此。
  • 心跳:实例定期向环发送心跳信号,表明它们正在运行。如果实例在一段时间内未发送心跳,则被视为不健康。