2. Loki 核心概念:架构、日志流、标签与日志条目详解
在深入标签与链路关联优化之前,必须牢固掌握 Loki 的四个核心抽象:架构设计、日志流(Log Stream)、标签(Label)与日志条目(Log Entry)。这些概念决定了日志如何被写入、索引、存储和查询,也是后续所有优化策略的基石。
2.1 Loki 整体架构设计
Loki 采用微服务架构,核心组件包括 Distributor、Ingester、Querier 和 Storage。与 Prometheus 类似,Loki 使用标签(Label)作为索引的唯一维度,日志内容本身不做全文索引,从而大幅降低存储成本。
架构要点:Loki 不解析日志内容,只根据标签建立索引。查询时通过标签匹配缩小范围,再扫描对应日志流中的条目。
2.2 日志流(Log Stream)
日志流是 Loki 中最核心的数据组织单元。一组具有完全相同标签集合的日志条目构成一个日志流。每个日志流在 Ingester 中对应一个内存缓冲区,最终持久化为一个或多个 Chunk。
关键理解:标签组合决定日志流数量。标签基数越高,日志流越多,Ingester 内存开销越大。合理控制标签基数(通常建议 < 10 个标签)是性能优化的第一步。
| 概念 | 定义 | 示例 |
|---|---|---|
| 日志流 | 具有相同标签集合的日志序列 | {job="api-server", env="prod"} |
| Chunk | 日志流的压缩存储单元 | 单个 Chunk 可包含数百至数千条日志 |
| 流哈希 | 标签集合的哈希值,用于分片和路由 | Distributor 根据哈希将日志转发至对应 Ingester |
2.3 标签(Label)
标签是 Loki 的唯一索引维度。每个标签是一个键值对(Key-Value),用于标识日志的来源、环境、服务等元信息。Loki 只对标签建立索引,不对日志内容建立全文索引。
标签分类
- 结构化标签:由日志采集器(Promtail、Alloy)或推送客户端自动附加,如
job、instance、__path__。 - 自定义标签:用户根据业务需求手动添加,如
service、env、team。 - 衍生标签(Derived Labels):通过 LogQL 的
label_format或 Relabel 规则从日志内容中提取。
标签设计原则
| 原则 | 说明 | 反例 |
|---|---|---|
| 低基数 | 每个标签的取值数量应有限(通常 < 100) | user_id(百万级取值) |
| 高区分度 | 标签应能有效缩小查询范围 | level=info(区分度低) |
| 稳定性 | 标签值不应频繁变化 | pod(每次重启变化) |
| 可枚举 | 标签值应可预定义,而非动态生成 | request_id(每次请求不同) |
常见陷阱:将高基数字段(如 trace_id、user_id、ip)直接作为标签,会导致日志流数量爆炸,Ingester 内存耗尽,查询性能急剧下降。高基数字段应放在日志内容中,通过 LogQL 的
|~ 或 json 解析器过滤。
2.4 日志条目(Log Entry)
日志条目是 Loki 存储的最小数据单元,包含三个部分:时间戳、日志行内容和元数据(可选)。
| 字段 | 类型 | 说明 |
|---|---|---|
| Timestamp | 纳秒精度 Unix 时间戳 | 日志产生的时间,用于排序和范围查询 |
| Line | 字符串 | 日志的原始文本内容 |
| Metadata(可选) | 键值对列表 | 附加的结构化信息,不参与索引 |
// 日志条目示例(JSON 序列化)
{
"stream": {
"job": "api-server",
"env": "prod",
"service": "user-svc"
},
"values": [
["1710000000000000000", "2025-03-09T12:00:00Z [INFO] 用户登录成功 userId=12345"],
["1710000001000000000", "2025-03-09T12:00:01Z [ERROR] 数据库连接超时 trace_id=abc-123"]
]
}
2.5 三者的关系
日志流、标签和日志条目之间的关系可以用下图概括:
2.6 与 OpenTelemetry 的关联点
在后续章节中,我们将利用这些核心概念实现日志与链路关联:
- 标签作为关联桥梁:将
trace_id、span_id作为标签,使日志流与链路直接绑定。 - 日志流隔离:按
service+env划分日志流,避免跨服务日志混流。 - 条目元数据:利用 Loki 2.x 的
structured_metadata功能,将链路上下文附加到日志条目中,不增加标签基数。
优化方向:在标签设计中预留
trace_id 标签位,但仅在需要关联的场景下使用,避免全局高基数。更优方案是使用结构化元数据(Structured Metadata)存储 trace_id,既保留关联能力,又不增加日志流数量。