2. Loki 核心架构:读写路径、核心组件与 Prometheus 异同
理解 Loki 的核心架构是设计日志检索 Golden Signals 指标的基础。Loki 的设计哲学与 Prometheus 高度一致:使用标签(Labels)对数据进行索引,而非对日志内容进行全文索引。这种设计大幅降低了存储成本和查询延迟,但也决定了其读写路径和组件职责的独特性。
2.1 Loki 整体架构概览
Loki 采用微服务架构,核心组件包括 Distributor、Ingester 和 Querier。它们协同工作,实现了日志数据的水平扩展和高可用。下图展示了 Loki 的核心架构与数据流。
2.2 核心组件职责详解
每个组件在读写路径中承担明确的职责,理解这些职责有助于我们定位性能瓶颈和设计告警规则。
| 组件 | 职责 | 关键特性 | 性能关注点 |
|---|---|---|---|
| Distributor | 接收日志写入请求,负责验证、去重、哈希分片,并将日志转发到正确的 Ingester。 | 无状态,可水平扩展;使用一致性哈希环确定目标 Ingester。 | 请求速率、验证失败率、转发延迟 |
| Ingester | 接收日志并缓存在内存中,定期将数据压缩并持久化到对象存储。负责日志的实时写入和近期数据查询。 | 有状态,数据在内存中;支持 WAL 防止数据丢失;数据按 chunk 组织。 | 内存使用率、chunk 刷写延迟、写入吞吐 |
| Querier | 接收 LogQL 查询请求,同时查询 Ingester(热数据)和对象存储(冷数据),合并结果后返回。 | 无状态,可水平扩展;支持查询并行化和缓存。 | 查询延迟、查询并发数、缓存命中率 |
设计启示: 在 Golden Signals 指标设计中,Distributor 的
rate 和 errors 反映写入可用性;Ingester 的 memory 和 flush latency 反映写入饱和度和延迟;Querier 的 query latency 和 error ratio 反映读取性能。
2.3 读写路径深度解析
写路径(Push Path)
- 日志采集:Promtail、Fluentd 或 OpenTelemetry Collector 采集日志,添加标签(如
job、instance、namespace)。 - Distributor 处理:验证日志流格式和标签合法性;基于标签哈希将日志流分片到对应的 Ingester 副本。
- Ingester 缓存:将日志追加到内存中的 chunk;当 chunk 达到大小或时间阈值时,压缩并写入对象存储。
读路径(Query Path)
- Querier 接收查询:Grafana 发送 LogQL 查询到 Querier。
- 并行查询:Querier 同时向所有 Ingester 查询内存中的热数据,并向对象存储查询历史冷数据。
- 结果合并:Querier 对来自多个 Ingester 和存储的结果进行去重、排序和聚合,返回最终结果。
2.4 Loki 与 Prometheus 的异同
Loki 的设计深受 Prometheus 影响,但两者在数据模型、存储和查询语言上存在本质差异。理解这些异同有助于复用已有的 Prometheus 运维经验。
| 维度 | Prometheus | Loki |
|---|---|---|
| 数据模型 | 时序指标(Metric + Labels),数值型 | 日志流(Stream = Labels),文本型 |
| 索引方式 | 基于标签的倒排索引 | 基于标签的倒排索引(仅索引标签,不索引日志内容) |
| 存储引擎 | TSDB(时序数据库),本地存储为主 | 对象存储(S3/GCS/MinIO),共享存储 |
| 查询语言 | PromQL(Prometheus Query Language) | LogQL(Log Query Language,兼容 PromQL 语法) |
| 数据保留 | 本地存储,受磁盘容量限制 | 对象存储,几乎无限扩展 |
| 水平扩展 | 通过联邦或 Thanos/Cortex 实现 | 原生微服务架构,组件独立扩展 |
| 典型用途 | 实时监控、告警、趋势分析 | 日志检索、故障排查、审计 |
核心差异总结:
- 索引策略相同:两者都使用标签索引,避免全文索引的高成本。这意味着 Loki 的查询性能高度依赖标签设计。
- 存储模型不同:Prometheus 是本地时序数据库,Loki 是共享对象存储。Loki 的存储成本更低,但查询延迟更高。
- 查询语言兼容:LogQL 复用了 PromQL 的聚合语法(如
rate、sum、topk),但增加了日志过滤和解析函数。
2.5 架构设计对 Golden Signals 的启示
Loki 的架构设计直接决定了我们在设计 Golden Signals 指标时需要关注的维度:
- 写入路径的延迟和错误:Distributor 和 Ingester 是写入瓶颈。监控
distributor_ingester_appends_total和ingester_chunk_utilization可以反映写入健康度。 - 读取路径的延迟和饱和度:Querier 的查询延迟和并发数直接影响用户体验。监控
querier_query_duration_seconds和querier_inflight_queries。 - 存储层的流量和错误:对象存储的请求速率和错误率是冷数据查询的关键。监控
loki_objectstore_requests_total。 - 标签基数控制:Loki 的索引性能与标签基数强相关。高基数标签(如
trace_id、user_ip)会导致 Distributor 和 Ingester 性能下降。
常见陷阱: 不要将 Prometheus 的指标设计经验直接照搬到 Loki。例如,Prometheus 中高基数的
request_id 标签在 Loki 中会导致严重的性能问题。Loki 的标签应保持低基数(通常 < 10 个唯一值),日志内容应通过 LogQL 的 |= 或 |~ 过滤。