2. etcd 基础回顾:Raft 协议、键值存储、Watch 机制、Lease 租约,以及它们在 Loki 中的角色
etcd 是 Loki 元数据存储的核心组件,负责保存日志流(Stream)的元数据、索引信息以及配置数据。理解 etcd 的四大基础机制——Raft 协议、键值存储、Watch 机制、Lease 租约——是后续分析写入放大与查询限流问题的前提。本节将逐一回顾这些机制,并明确它们在 Loki 架构中的具体角色。
2.1 Raft 协议:分布式一致性的基石
Raft 是一种用于管理复制日志的共识算法,它将问题分解为领导者选举、日志复制和安全性三个子问题。etcd 使用 Raft 保证集群中所有节点数据的一致性。
- Leader(领导者): 处理所有客户端请求,负责日志复制。
- Follower(跟随者): 被动接收来自 Leader 的日志条目。
- Candidate(候选者): 在选举超时后发起新一轮选举。
在 Loki 中的角色: Loki 的 Ingester 组件将日志流元数据写入 etcd 时,请求首先到达 Raft Leader。Leader 将写入操作封装为日志条目,复制到多数 Follower 节点后,才返回成功响应。这一过程确保了元数据的高可用性和强一致性,但也是写入放大(Write Amplification)的根源之一——每次写入在集群内部被复制多次。
2.2 键值存储:元数据的组织方式
etcd 是一个分布式的键值存储系统,数据以目录结构组织。键(Key)是唯一的,值(Value)可以是任意字节序列。etcd 支持前缀查询、范围查询和事务操作。
| 概念 | 说明 | Loki 中的使用 |
|---|---|---|
| Key | 唯一标识,支持分层路径(如 /loki/index/<tenant>/<stream>) |
日志流 ID、索引条目、配置项 |
| Value | 存储的数据内容,大小有限制(默认 1.5 MiB) | 日志流标签集合、时间戳范围、chunk 引用 |
| Revision | 全局单调递增的版本号,每次修改递增 | 用于 Watch 机制和 MVCC 控制 |
| Lease | 关联到 Key 的租约,到期自动删除 | Ingester 心跳、临时元数据清理 |
2.3 Watch 机制:事件驱动的元数据同步
Watch 机制允许客户端监听特定 Key 或前缀的变化。当被监听的 Key 发生创建、更新、删除操作时,etcd 会向所有 Watch 客户端推送事件通知。
Watch 的工作流程:
- 客户端通过 gRPC 建立 Watch 连接,指定监听的 Key 或前缀。
- etcd 在内存中维护 Watch 列表,记录每个 Watch 的起始 Revision。
- 当有写入操作发生时,etcd 将事件(Event)追加到事件历史缓冲区。
- etcd 异步将事件推送给匹配的 Watch 客户端。
在 Loki 中的角色:
- Ingester 注册与发现: Ingester 启动时在 etcd 中注册自身信息,Querier 通过 Watch 监听 Ingester 列表的变化,动态感知哪些 Ingester 持有哪些日志流。
- 元数据变更通知: 当日志流元数据更新时,Watch 机制通知相关组件刷新缓存。
- 限流风险: 大量日志流频繁创建/删除会导致 Watch 事件风暴,触发 etcd 的限流机制(如
--max-request-bytes和--quota-backend-bytes),这是查询限流问题的关键诱因。
2.4 Lease 租约:临时元数据的生命周期管理
Lease(租约)是 etcd 提供的一种 TTL(Time-To-Live)机制。客户端可以创建一个 Lease,设置过期时间,然后将 Key 关联到该 Lease。当 Lease 过期时,所有关联的 Key 会被自动删除。
Lease 的核心特性:
- 创建与续期: 客户端创建 Lease 后,需要定期发送 KeepAlive 请求续期。
- 关联 Key: 一个 Lease 可以关联多个 Key,一个 Key 只能关联一个 Lease。
- 自动清理: Lease 过期后,etcd 自动删除所有关联的 Key,释放存储空间。
- 租约时间: 默认 TTL 可配置,Loki 中通常设置为 10-30 秒。
在 Loki 中的角色:
| 场景 | Lease 用途 | 影响 |
|---|---|---|
| Ingester 心跳 | 每个 Ingester 创建一个 Lease,定期续期,标识自身存活 | Lease 过期表示 Ingester 宕机,触发元数据重新分配 |
| 临时流元数据 | 新创建的日志流元数据关联短 TTL Lease | 避免因 Ingester 崩溃导致残留元数据堆积 |
| 分布式锁 | Compactor 使用 Lease 实现任务锁,防止并发冲突 | 确保数据压缩任务的唯一性 |
2.5 四大机制在 Loki 中的协同关系
etcd 的四大机制并非独立运行,而是在 Loki 中形成紧密的协同关系。下表总结了它们之间的交互和影响:
| 机制 | 主要功能 | Loki 组件 | 性能影响 |
|---|---|---|---|
| Raft 协议 | 保证元数据一致性 | 所有写入操作 | 写入放大 3x(3 节点集群) |
| 键值存储 | 元数据持久化 | Ingester、Querier、Compactor | 键空间膨胀导致查询延迟 |
| Watch 机制 | 事件驱动的同步 | Querier、Distributor | 事件风暴触发限流 |
| Lease 租约 | 临时元数据生命周期 | Ingester、Compactor | KeepAlive 请求增加写入负载 |
- Raft 复制是写入放大的根本原因——每次元数据写入在集群内部被复制多次。
- Watch 事件风暴是查询限流的直接触发因素——大量 Watch 事件导致 etcd 拒绝新请求。
- Lease 续期请求叠加在写入放大之上,进一步压榨 etcd 的写入吞吐。
- 键值存储的膨胀速度决定了 etcd 的存储压力和查询性能退化速度。