Grafana Tempo 感知可用区的 live-store 复制(Zone-aware live-stores)配置指南
2026/9/18 19:53:42 网站建设 项目流程

Grafana Tempo 感知可用区的 live-store 复制(Zone-aware live-stores)配置指南

【免费下载链接】tempoGrafana Tempo is a high volume, minimal dependency distributed tracing backend.项目地址: https://gitcode.com/GitHub_Trending/tempo1/tempo

Zone awareness(区域感知/故障域感知)是 Tempo 用于保证数据在多个故障域(下称"区域 zone")之间冗余复制、从而提升整体可用性的关键能力。本指南聚焦于 live-store(实时存储)场景下的 zone-aware 复制配置:它将 Tempo 的分区(partition)所有权按"每个区域一个 live-store"进行分配,使任一区域中的 live-store 不可用时,其他区域的 live-store 仍能继续为该分区提供查询服务。读完本文,你将理解 zone-aware live-stores 的工作原理(RF2 复制、读仲裁为 1 的机制)、如何在 Tempo 中为 live-store 与查询端配置感知可用区的路由,以及与此相关的 ring、partition ring 配置参数的含义与作用。

一、Zone awareness 是什么

Zone awareness 是一项确保数据跨故障域复制、从而提供更高可靠性的功能。这里的"故障域"(failure domain)完全由你自行定义,常见的有:

  • 云厂商的可用区(availability zone,如 AWS 的us-east-1a);
  • 数据中心(data center);
  • 服务器机架(server rack)。

对 Grafana Tempo 而言,配置 zone awareness 后,系统会把 ring 中的每个实例标记到它所属的区域,并将数据副本放置到不同区域,从而避免"整个区域故障时所有副本同时不可用"的最坏情况。

Tempo 是一个"高吞吐、最小依赖"的分布式链路追踪后端(参见 README.md),zone awareness 与它的 ring 机制深度绑定:每个参与服务的实例会通过 key-value 存储(默认 memberlist)向 ring 注册自己的身份、地址与区域归属

二、Zone-aware live-stores 的核心设计

每个分区由"每个区域一个 live-store"持有

当为 live-stores 开启 zone awareness 后,Tempo 的每个分区(partition)将由每个区域中的一个 live-store 持有(owned)。也就是说,若你部署了 3 个区域,那么每个分区会有 3 个 live-store 同时持有它——分别位于 3 个不同的区域。

这样做的好处是:当某个区域中的 live-store 不可用时,其他区域中持有同一分区的 live-store 可以继续为该分区提供查询服务,查询不会中断。

RF2 复制与读仲裁为 1

在这种设计下:

  • 数据跨区域复制,副本数为 2(RF2):每个分区在两个不同区域中保有数据副本;
  • 读仲裁(read quorum)为 1:查询端(querier)只需获得每个分区的一个live-store 的响应即可返回结果。

也就是说,虽然数据写入了两份,但查询只需要一份响应即可成功。这带来了一个重要收益:读路径无需进行数据去重(data deduplication),因为查询只依赖单一副本的结果,不会对来自多个副本的响应做合并比对。这一点同时降低了查询延迟(等待最少响应即可返回)与实现复杂度。

设计要点小结

设计维度行为
分区所有权每个分区在每个区域中恰有一个 live-store 持有
复制因子跨区域 RF2,数据写入两个区域
读仲裁每分区仅需 1 个 live-store 响应(quorum = 1)
读路径去重不需要;查询只取单副本结果
故障场景单一区域 live-store 不可用时,其余区域副本继续服务查询

三、live-store 在 Tempo 中的角色与 ring 机制

live-store 模块概览

live-store 是 Tempo 的 livestore 模块提供的能力,负责从 Kafka 消费 trace 数据、在内存中维护实时数据分片(live traces)、并按块(block)完成与刷新到后端存储。与其相关的重要源文件包括:

  • live_store.go:核心服务,同时管理分区 ring(partition ring)读 ring(read ring)
  • partition_ring.go:分区 ring 的配置与生命周期器(lifecycler)参数;
  • partition_reader.go:按分区消费 Kafka、计算滞后(lag)并提交 offset 的读取器;
  • config.go:live-store 全部配置项及其默认值。

两个 ring:分区 ring 与读 ring

从源码 live_store.go 可以看到,LiveStore 启动时会同时搭建两套 ring:

  1. 分区 ring(partition ring):基于ring.NewPartitionInstanceLifecycler构建,用于管理"谁持有哪个分区"的所有权关系。每个分区可以有多位 owner(不同区域的 live-store 各占其一),这正是 zone-aware 复制的基础;
  2. 读 ring(read ring / membership ring):基于ring.NewBasicLifecycler构建,用于服务发现——live-store 实例注册到 ring 中,让查询端可以发现并连接。从 live_store.go 的实现可以看到,该 ring 的实例注册为ring.ACTIVE状态且不需要 token(注释明确说明"我们只需要在 ring 里以做服务发现")。

关键配置项instance_zone(源码定义于 pkg/ring/config.go)正是用于在 ring 中标记实例所属区域:BasicLifecyclerConfig中的Zone字段取自cfg.InstanceZone(参见 pkg/ring/config.go)。每个 live-store 实例只要配置了不同的instance_zone,就会被 ring 归属到不同区域,从而实现"每分区每区域一个 owner"的布局。

此外,分区读取器还通过tempo_live_store_partition_owned指标(带有partitionzone两个标签)暴露当前实例对分区的持有状态,方便运维直接观察每个分区在每个区域的所有权情况(见 partition_reader.go)。

四、如何配置 zone-aware live-stores

配置区域归属(instance_zone)

要让 zone awareness 生效,第一步是给每个 live-store 实例设置区域标识。Tempo 的统一配置结构(模块livestorering段)中对应字段为:

livestore: ring: # 必填:定义当前实例所属的故障域。 # 可以是可用区、数据中心或机架名,例如 "us-east-1a"、"dc1"、"rack-a"。 instance_zone: "us-east-1a"

该配置的源码定义位于 pkg/ring/config.go:RegisterFlagsAndApplyDefaults中通过 flag-<prefix>.instance-availability-zone注册(例如-livestore.ring.instance-availability-zone),默认值为空字符串(即默认不感知区域)。它最终会被写入BasicLifecyclerConfig.Zone(pkg/ring/config.go),随心跳上报到 ring,供查询端按区域选择实例。

务必确保:同一分区副本所在的多个 live-store 实例必须配置互不相同instance_zone,否则它们会落入同一故障域,区复制(RF2)的容灾效果将大打折扣。

分区 ring 的 KV 存储

分区 ring 的状态共享依赖于 KV 存储。从 partition_ring.go 可以看到,其默认 store 为memberlist(默认前缀collectors/),一般无需改动:

livestore: partition_ring: kvstore: store: memberlist

完整的最小配置示例

结合 config.go 中RegisterFlagsAndApplyDefaults的默认值(如HeartbeatPeriod = 5sHeartbeatTimeout = 1m),一个开启 zone-aware 的最小配置如下:

livestore: ring: heartbeat_period: 5s # 默认 5s,ring 心跳周期 heartbeat_timeout: 1m # 默认 1m,心跳超时判定实例不健康 instance_zone: "us-east-1a" # 关键:本实例所属区域,各副本实例必须互不相同 partition_ring: kvstore: store: memberlist # 默认 memberlist,无需手动指定也可 min_partition_owners_count: 1 # PENDING 分区转为 ACTIVE 所需的最少 owner 数 min_partition_owners_duration: 10s # 满足最小 owner 数后需持续的时间 delete_inactive_partition_after: 13h # INACTIVE 分区被删除前的等待时长

其中min_partition_owners_countmin_partition_owners_durationdelete_inactive_partition_after三个参数在 partition_ring.go 中均有注释说明其映射关系:

  • MinOwnersCountPartitionInstanceLifecyclerConfig.WaitOwnersCountOnPending
  • MinOwnersDurationWaitOwnersDurationOnPending
  • DeleteInactivePartitionAfterDeleteInactivePartitionAfterDuration

对于 zone-aware 场景,建议min_partition_owners_count至少设为你的区域数量(例如 2 或 3),确保分区只有在每个区域都有 owner 之后才转为 ACTIVE 对外服务。

五、查询端如何感知区域:PreferredZone 与 zone sorter

仅让 live-store 感知区域还不够,查询端(querier)也需要按区域组织请求,尽量在本地/优先区域内完成查询。这一逻辑实现在 querier/partition_ring.go:

  • queryQuorumConfigForReplicationSets构造ring.DoUntilQuorumConfig,并通过queryPartitionRingZoneSorter(q.cfg.PartitionRing.PreferredZone)注入一个区域排序器(querier/partition_ring.go);
  • 排序器逻辑(querier/partition_ring.go)为:若preferredZone非空,则把该区域排到最前优先尝试;其余区域打乱顺序以均衡负载。这样在"最小化请求 + 按区域优先"的配合下,querier 会优先访问同区域副本,区域不可用时再退回到其他区域副本。
querier: partition_ring: preferred_zone: "us-east-1a" # 优先查询该区域内的 live-store 副本 minimize_requests: true # 达到仲裁(每分区 1 个响应)后即停止多余请求

minimize_requestsminimize_requests_hedging_delay直接映射到DoUntilQuorumConfig的对应字段(querier/partition_ring.go),用于控制达到 quorum=1 后是否立即终止其余 in-flight 请求。

六、zone-aware 复制的收益与适用场景

收益

  1. 高可用:单个区域(可用区/数据中心/机架)故障不会中断对应分区的查询,另一区域的副本继续服务;
  2. 低查询开销:读仲裁为 1,querier 只需等待一个副本响应,不会因为等待多个副本而放大延迟;
  3. 实现简单:读路径无需数据去重,省去多副本结果合并的复杂性与额外 CPU/内存开销;
  4. 负载均衡:zone sorter 在多个区域间随机打散请求顺序,避免查询全部打在单一区域副本上。

适用场景

  • 多可用区部署的云原生环境(如 EKS/GKE/ACK 上跨 AZ 部署 Tempo 微服务形态);
  • 需要保证 trace 查询在基础设施局部故障期间仍可用的生产集群;
  • 追求读写路径低复杂度、同时具备跨域冗余能力的高吞吐 tracing 后端。

注意事项

  • instance_zone必须按故障域真实布局填写并保持一致,错误配置会导致所有副本落入同一区域,失去容灾意义;
  • 复制因子与仲裁关系是固定的(RF2 + quorum 1),不要尝试通过修改ReplicationFactor等底层 ring 参数去改变该语义(pkg/ring/config.go 中ToRingConfig固定设置ReplicationFactor = 1,因为真正承担复制的语义由分区所有权与区域分配实现);
  • 部署新区域或下线区域时,注意delete_inactive_partition_after(默认 13h)对分区状态转换的影响,避免分区长期滞留 INACTIVE。

七、进一步阅读

  • 完整配置参考:frontend/docs/config-reference.md(其中包含livestore.ring.instance_zonequerier.partition_ring.preferred_zone等字段的 YAML 示例);
  • live-store 配置与默认值:config.go;
  • 分区 ring 配置:partition_ring.go;
  • 查询端 zone sorter 实现:querier/partition_ring.go;
  • ring 配置(instance_zoneheartbeat_periodheartbeat_timeout):pkg/ring/config.go。

【免费下载链接】tempoGrafana Tempo is a high volume, minimal dependency distributed tracing backend.项目地址: https://gitcode.com/GitHub_Trending/tempo1/tempo

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询