2. Loki基础架构:组件、日志流与标签设计原则
2.1 核心组件与职责
Loki采用微服务架构,其核心组件包括Distributor(分发器)、Ingester(写入器)和Querier(查询器)。三者协同工作,实现日志数据的接收、存储与检索。
架构要点: 所有组件均无状态(除Ingester持有短暂内存数据),可通过水平扩展提升吞吐与可用性。
2.2 组件职责详解
| 组件 | 核心职责 | 关键特性 |
|---|---|---|
| Distributor | 接收日志写入请求,验证数据合法性,按标签哈希分片转发至对应Ingester | 无状态、可水平扩展;支持速率限制与数据校验 |
| Ingester | 接收日志流并写入内存,定期将数据刷入对象存储;响应Querier对热数据的查询 | 持有最近N小时数据(可配置);故障时通过WAL恢复 |
| Querier | 接收LogQL查询请求,同时从Ingester(热数据)和对象存储(冷数据)拉取日志,合并去重后返回 | 无状态;支持并行查询与缓存加速 |
实践提示: 生产环境中建议将Ingester的内存保留时间设为1-3小时,平衡查询性能与故障恢复成本。
2.3 日志流与标签设计原则
日志流(Log Stream)是Loki中数据组织的基本单元。具有相同标签集合的日志条目属于同一个流。标签设计直接影响查询效率与存储成本。
标签设计核心原则
- 高基数标签禁止作为主标签: 如
user_id、request_id、ip等取值过多的字段,应作为日志内容而非标签。 - 低基数标签优先: 如
job、level、service、environment、cluster。 - 标签数量控制在5-8个: 过多标签导致流数量爆炸,增加Ingester内存压力。
- 使用结构化解析替代标签: 通过LogQL的
| json、| logfmt、| regexp等解析器提取字段,而非全部做成标签。
2.4 Loki与Prometheus的异同
Loki的设计理念深受Prometheus影响,但两者在数据模型、存储目标和查询语言上存在本质差异。
| 对比维度 | Prometheus | Loki |
|---|---|---|
| 数据类型 | 时序数值(指标) | 日志文本(事件) |
| 标签作用 | 标识时间序列,用于聚合与过滤 | 标识日志流,用于快速定位日志来源 |
| 数据内容 | 数值点(float64 + 时间戳) | 日志行(字符串 + 时间戳 + 元数据) |
| 查询语言 | PromQL(聚合、预测、数学运算) | LogQL(过滤、解析、标签提取、指标聚合) |
| 存储引擎 | TSDB(时序块压缩) | 对象存储 + 索引(日志块压缩) |
| 索引策略 | 基于标签的倒排索引 | 基于标签的倒排索引 + 日志内容不索引 |
| 水平扩展 | 通过Thanos/Cortex实现 | 原生微服务架构,天然支持 |
| 典型场景 | 告警、仪表盘、容量规划 | 故障排查、审计、日志分析 |
常见误区: 不要试图用Loki替代Prometheus做实时告警(延迟较高),也不要用Prometheus存储日志文本。两者是互补关系,而非替代关系。
2.5 架构设计带来的工程优势
- 低成本存储: 日志内容不建索引,仅索引标签,存储成本仅为Elasticsearch的1/5-1/10。
- 原生云原生: 与Kubernetes深度集成,自动发现Pod日志,无需额外采集配置。
- 查询与写入分离: Distributor和Querier独立扩展,写入高峰不影响查询性能。
- 热冷分层: Ingester内存数据提供毫秒级查询,对象存储数据支持大规模历史检索。