2. Loki 核心架构:组件、读写路径与 Prometheus 异同
Loki 的架构设计围绕“日志即数据流”的理念展开,将日志的接收、存储、查询与压缩解耦为多个独立组件。理解这些组件及其协作路径,是构建可靠日志门禁系统的基础。本章从组件职责、读写路径以及与 Prometheus 的对比三个维度展开。
2.1 核心组件与职责
Loki 采用微服务架构,各组件可独立部署与扩缩容。下表列出了生产环境中最重要的五个组件及其核心职责:
| 组件 | 职责 | 关键特性 |
|---|---|---|
| Distributor | 接收来自 Promtail 或 SDK 的日志流,验证数据合法性,并通过一致性哈希将日志分片转发至对应的 Ingester。 | 无状态、可水平扩展;负责数据准入与负载均衡。 |
| Ingester | 接收 Distributor 推送的日志,在内存中构建索引和块(chunk),并将块异步写入对象存储(如 S3、GCS)。 | 有状态;负责数据写入与短期缓存;支持故障转移。 |
| Querier | 处理 LogQL 查询请求,从 Ingester(热数据)和对象存储(冷数据)中拉取日志块,合并结果后返回。 | 无状态;负责查询路由与结果聚合。 |
| Compactor | 定期合并对象存储中的小索引和块,删除过期数据,优化存储布局。 | 后台任务;降低存储成本并提升查询效率。 |
| Query Frontend | 可选组件,位于 Querier 之前,负责查询拆分、缓存和限流。 | 提升大规模并发查询性能。 |
生产建议: 在蓝绿发布门禁场景中,Distributor 和 Querier 应优先配置多副本,避免单点故障导致日志写入或查询中断。
2.2 读写路径详解
Loki 的读写路径是架构的核心。写入路径强调低延迟与高吞吐,读取路径则强调索引效率与数据合并。下图展示了完整的读写流程:
写入路径(Write Path):
- 数据采集: Promtail 或应用 SDK 将日志流推送到 Distributor 的 HTTP/gRPC 端点。
- 数据分片: Distributor 根据日志标签(label)计算一致性哈希,将日志转发至对应的 Ingester 副本。
- 内存缓冲与持久化: Ingester 将日志追加到内存中的流(stream),按时间或大小阈值切割为块(chunk),异步上传至对象存储。
读取路径(Read Path):
- 查询发起: Grafana 或 API 发送 LogQL 查询到 Query Frontend(或直接到 Querier)。
- 查询拆分: Query Frontend 将大查询按时间范围拆分为多个子查询,并缓存结果。
- 数据合并: Querier 并行查询 Ingester(热数据)和对象存储(冷数据),合并结果后返回。
2.3 与 Prometheus 的异同
Loki 的设计深受 Prometheus 影响,但两者在数据模型、存储目标和查询语言上存在本质差异。下表从六个关键维度进行对比:
| 维度 | Prometheus | Loki |
|---|---|---|
| 数据类型 | 数值型时间序列(指标) | 文本型日志行(事件) |
| 索引方式 | 基于标签(label)的倒排索引 | 基于标签的倒排索引 + 日志内容全文索引(可选) |
| 存储内容 | 数值 + 时间戳 | 日志文本 + 元数据(标签、时间戳) |
| 查询语言 | PromQL(聚合、运算、预测) | LogQL(过滤、解析、指标提取) |
| 数据压缩 | gorilla 压缩(浮点数) | gzip / snappy / lz4(文本块) |
| 典型场景 | 告警、监控、容量规划 | 日志审计、故障排查、门禁分析 |
架构误区提醒: 不要将 Loki 视为 Prometheus 的“日志版”。Prometheus 的拉模型(pull)与 Loki 的推模型(push)在数据采集、存储和查询优化上完全不同。在蓝绿发布门禁中,Loki 更适合记录每次发布的日志事件流,而 Prometheus 更适合监控发布过程中的 CPU/内存/错误率指标。
2.4 组件协作与扩展性
Loki 的组件协作遵循“无共享”原则,每个组件均可独立扩缩容。下图展示了组件间的数据流与依赖关系:
扩展性要点:
- Distributor / Querier / Query Frontend: 无状态组件,通过增加副本数线性提升吞吐量。
- Ingester: 有状态组件,扩缩容需配合数据重新分片(ring 调整),建议使用 StatefulSet 部署。
- Compactor: 单副本即可,资源消耗与存储数据量成正比。