菜单
开源

0004: 索引网关分片

作者: Christian Haudum ( christian.haudum@grafana.com)

日期 02/2023

赞助者: @chaudum @owen-d

类型: 功能

状态: 已拒绝 / 未实现

相关问题/PR

来自邮件列表的讨论


背景

本文档旨在提出一个关于如何更好地在索引网关上进行数据分片的提案,以便我们能够水平扩展服务,满足大型租户日益增长的元数据查询需求。

索引网关服务可以运行在“简单模式”下,此时每个索引网关实例负责处理、存储和返回所有租户的所有索引请求;或者运行在“环模式”下,此时一个实例负责处理一部分租户的请求,而非所有租户。

此外,为了实现冗余和分散负载,索引网关环默认使用复制因子 3。

这意味着,在索引网关客户端向索引网关服务器发出请求之前,它会首先对租户 ID 进行哈希计算,然后从索引网关环中请求该哈希对应的复制集。由于复制因子 (RF) 是固定的,复制集包含三个服务器地址。对于每个请求,会从该列表中随机选择一个服务器来执行请求。

问题陈述

当前按租户 ID 进行分片并使用复制因子的策略从长远来看是失败的,因为即使运行了大量的索引网关,单个租户最多也只能利用 n 个实例,其中 n 是配置的 RF 值。

另一个问题是 RF 是固定的,并且对所有租户都是相同的,这与他们在日志量或查询速率方面的实际大小无关。

目标

本文档的目标是为索引网关找到一种更好的分片机制,以便服务的水平扩展没有限制。

  • 分片需要考虑租户的“大小”。
  • 单个租户需要能够利用超过三个索引网关。

提案

提案 0:不采取任何行动

如果我们不改进索引网关的分片机制并保持现状,那么为大型租户提供元数据查询的服务将在合理的时间内变得越来越困难,这与对这些查询的需求成比例。

提案 1:动态复制因子

复制因子不是固定为 3,而是可以根据索引网关环中活动成员的数量来确定。这意味着 RF 将是可用网关实例的百分比。例如,一个包含 12 个实例且复制利用率为 30% 的环,其 RF 将为 3 (floor(12*0.3))。扩展到 18 个实例将导致 RF 为 5。

这种方法可以解决水平扩展的问题。然而,它不能解决不同租户大小的问题。除非 RF 有固定的下限值,否则在运行少量实例时也无法确保可用性的复制。在大型索引网关部署中,它也倾向于过度分片数据。

提案 2:固定的每个租户复制因子

在租户 ID 中添加一个随机的分片 ID(例如 shard-0, shard-1, … shard-n)可以利用一定数量的 n 个实例。分片数量可以作为每个租户的覆盖设置来实现。这将允许为每个租户使用不同数量的实例。但是,这种方法会导致非确定性哈希键。

提案 3:按索引文件分片

为了响应请求,索引网关需要从对象存储下载索引文件,并且由于 Loki 为每个租户每天构建一个索引文件,这些索引文件可以均匀地分片到所有可用的索引网关实例。然后,每个实例被分配一组唯一的索引文件,它可以针对这些文件响应元数据查询。

这意味着分片键是对象存储中的文件名。虽然这个文件名编码了租户和日期,但这并非严格必要。这种分片机制可以将对象存储中的任何文件分片到一个环中的一组实例上。

如果请求的元数据的时间范围在一天之内,则单个索引网关实例可以响应元数据请求。然而,如果元数据请求跨越多天,则会涉及多个索引网关实例。有两种方法可以解决这个问题

A) 在客户端拆分和合并

客户端解析所需的索引文件及其各自的网关实例。它将请求拆分为多个子请求,执行这些请求并将它们合并为一个结果。

优点

  • 只执行最少的必要请求。

缺点

  • 客户端需要知道如何拆分和合并请求的信息。

B) 在索引网关处理程序端拆分和合并

客户端可以在任何索引网关上执行请求。然后,此处理程序实例识别涉及的索引文件,拆分查询,并解析适当的实例。一旦收到子查询结果,它就会重新组合完整的响应结果并将其发送回客户端。

优点

  • 分片对客户端透明处理。
  • 客户端可以与索引网关环中的任何实例通信。
  • 关于拆分和合并的领域信息保留在索引网关服务器实现内部。

由于其架构优势,推荐选项 B。

其他说明

提案 3 的架构图

index gateway sharding