@Greptime: trace_id 是高基数——所以小米智慧工厂团队没有使用倒排索引。他们使用了 Bloom 跳跃索引…
摘要
小米智慧工厂用 GreptimeDB 替换了 Loki 进行日志存储,每月处理数十亿行数据,并采用了定制化索引:针对高基数的 trace_id 使用 Bloom 跳跃索引,针对低基数字段使用倒排索引,并对消息体进行全文搜索。
查看缓存全文
缓存时间: 2026/06/24 07:59
trace_id 是高基数字段——所以小米智能工厂团队没有选择倒排索引,而是为它配置了布隆跳过索引。低基数字段(log_level、service)使用倒排索引;message 字段使用全文索引。为每个字段匹配最合适的索引类型。每月处理数十亿行日志,在 GreptimeDB 上实现亚秒级 TraceID 查询,Promtail 保持不变。另请参阅用 GreptimeDB 替代 Loki 的另一个案例:https://greptime.com/blogs/2026-06-22-xiaomi-factory-log-case… — # 小米智能工厂如何在 GreptimeDB 上存储系统交互日志 来源:https://greptime.com/blogs/2026-06-22-xiaomi-factory-log-case 小米智能工厂使用 GreptimeDB 存储其系统交互日志,每月处理数十亿行数据,并支持快速的索引检索。随着日志量增长,团队从基于 Loki 的流水线迁移到 GreptimeDB,并在采集侧保留 Promtail。以下是他们的构建过程及经验总结。
背景(https://greptime.com/blogs/2026-06-22-xiaomi-factory-log-case#background)
在小米智能工厂的数字化运营中,日志监控系统至关重要。它实时采集设备与业务系统之间的交互日志,帮助工程师快速定位问题并追踪调用链路。存储在 GreptimeDB 中的是系统交互日志,用于服务调用故障排查、链路追踪和运行时诊断。随着部署规模扩大,部分工厂提出了合规要求,例如本地部署:他们希望系统交互日志的采集、存储和查询完全在工厂自己的私有集群内完成。
对于核心服务,单月系统交互日志可达数十亿行,这对存储和检索方案提出了很高要求:
- 大时间范围查询:跨小时或天级别窗口检索日志必须保持稳定,永不超时。
- 全文关键词搜索:工程师需要能够通过关键词在大规模日志内容中快速定位条目。
- 基于 TraceID 的链路追踪:通过 TraceID 追踪跨服务调用路径,要求近乎瞬时的响应。
工程团队需要一个能够处理数十亿行日志存储、提供高效索引检索,并兼容成熟行业标准采集管道的解决方案。
解决方案概述(https://greptime.com/blogs/2026-06-22-xiaomi-factory-log-case#solution-overview)
经过评估和验证,小米的系统交互日志解决方案采用 Promtail 进行采集,GreptimeDB 作为存储和查询基础。在日志工作负载上的公开基准测试也指向相同结论:与 Loki 相比,GreptimeDB 的写入吞吐量提升约 1.5 倍,查询速度快 40–80 倍,存储节省约 50%(请参阅我们的 GreptimeDB vs. Loki 日志性能报告:https://greptime.com/blogs/2025-08-07-beyond-loki-greptimedb-log-scenario-performance-report)。主要原因如下:
原生 Promtail 支持(https://greptime.com/blogs/2026-06-22-xiaomi-factory-log-case#native-promtail-support)
GreptimeDB 暴露了 Loki Push API,因此 Promtail 可以直接将日志推送到 GreptimeDB,无需替换采集代理。现有的 Promtail 配置和日志格式定义无需改动即可沿用。
丰富的索引选项(https://greptime.com/blogs/2026-06-22-xiaomi-factory-log-case#rich-indexing-options)
GreptimeDB 提供多种索引类型,可以根据字段的查询模式为其选择最合适的策略:
| 索引类型 | 最佳适用场景 | 示例字段 |
|---|---|---|
| 跳过索引 | 高基数字段等值查找 | trace_id、span_id |
| 倒排索引 | 低基数字段过滤 | log_level、service |
| 全文索引 | 日志内容的关键词搜索 | message |
SQL 查询支持(https://greptime.com/blogs/2026-06-22-xiaomi-factory-log-case#sql-query-support)
GreptimeDB 支持标准 SQL,工程师可以使用他们熟悉的语法进行复杂的日志分析。
自动 Schema 演进(https://greptime.com/blogs/2026-06-22-xiaomi-factory-log-case#automatic-schema-evolution)
日志字段经常变化。GreptimeDB 会自动推断新字段的类型并扩展表 schema,无需手动维护 schema。
架构(https://greptime.com/blogs/2026-06-22-xiaomi-factory-log-case#architecture)
系统交互日志的整体架构如下:
日志采集管道:工厂服务 → Promtail → GreptimeDB → Grafana
每个阶段职责清晰:
- Promtail 采集:在每个节点上运行,采集日志文件并通过 HTTP 推送。
- 管道解析:使用 VRL 脚本将 JSON 日志解析为结构化字段。
- 多级索引:为每个字段配置适合其查询模式的索引。
- SQL 查询:Grafana 通过 GreptimeDB 插件以 SQL 方式查询日志。
GreptimeDB 存储解析后的系统交互日志字段,用于运行时诊断、调用路径故障排查和日志检索。
部署指南(https://greptime.com/blogs/2026-06-22-xiaomi-factory-log-case#deployment-walkthrough)
步骤 1:配置日志推送端点(https://greptime.com/blogs/2026-06-22-xiaomi-factory-log-case#step-1-configure-the-log-push-endpoint)
Promtail 通过 GreptimeDB 提供的 Loki Push API 推送日志:
clients:
- url: http://<greptimedb_host>:4000/v1/loki/api/v1/push
headers:
Authorization: "Basic <base64_encoded_credentials>"
x-greptime-db-name: "public"
x-greptime-log-table-name: "system_interaction_logs"
关于认证的说明:GreptimeDB 使用 HTTP Basic Auth,因此需要将 username:password 进行 Base64 编码后放入 Authorization 头。
提示:如果遇到认证错误,请首先检查 Basic Auth 配置。这是最常见的部署问题。
步骤 2:配置管道解析 JSON 日志(https://greptime.com/blogs/2026-06-22-xiaomi-factory-log-case#step-2-configure-a-pipeline-to-parse-json-logs)
系统交互日志采用 JSON 格式,包含许多结构化字段。为了将这些字段提取到独立的列中,需要配置 GreptimeDB 管道。从 v0.15 开始,GreptimeDB 支持 VRL(Vector Remap Language)处理器。以下是一个示例配置:
version: 2
processors:
- vrl:
source: |
msg = parse_json!(.loki_line)
. = {
"log_time": parse_timestamp!(msg.timestamp, "%Y-%m-%d %T%.3f"),
"log_level": msg.level,
"logger": msg.logger,
"message": msg.message,
"exception": msg.exception,
"service": .loki_label_job,
"server_ip": msg.server_address,
"client_ip": msg.client_ip,
"thread": msg.thread,
"duration_ms": to_float!(msg.time_spent),
"trace_id": msg.trace_id,
"span_id": msg.span_id,
}
transform:
- field: log_time
type: time, ms
index: timestamp
几点需要注意:
- 使用
\.loki_line:通过 Loki Push API 写入时,日志体映射到 GreptimeDB 中的loki_line字段。 - 使用
\.loki_label_*:Promtail 标签在 GreptimeDB 中以loki_label_前缀访问。 - 时间戳处理:
parse_timestamp!从日志中解析时间戳并将其用作时间索引。
创建管道后,在 Promtail 配置中引用它:
headers:
x-greptime-pipeline-name: "system-interaction-log-json-parse"
步骤 3:添加索引以加速查询(https://greptime.com/blogs/2026-06-22-xiaomi-factory-log-case#step-3-add-indexes-to-speed-up-queries)
根据实际查询模式,为每个关键字段配置合适的索引。小米团队在 trace_id 上设置了布隆类型的跳过索引:
ALTER TABLE system_interaction_logs MODIFY COLUMN trace_id SET SKIPPING INDEX WITH(
granularity = 4096,
type = 'BLOOM',
false_positive_rate = 0.01
);
索引调优提示:
granularity越小,查询越快,但索引也越大。- 如果查询性能仍不满足要求,可尝试将 granularity 降低到 2048 或 1024。
- 索引变更仅对新写入的数据生效;现有数据的索引不会重建。
为日志内容启用全文搜索:
ALTER TABLE system_interaction_logs MODIFY COLUMN message SET FULLTEXT INDEX;
步骤 4:配置 Grafana 数据源(https://greptime.com/blogs/2026-06-22-xiaomi-factory-log-case#step-4-configure-the-grafana-data-source)
使用 GreptimeDB Grafana 插件查询日志:
- 安装 GreptimeDB Grafana 数据源插件(https://docs.greptime.com/user-guide/integrations/grafana/)
- 配置数据源连接
- 在仪表板中使用 SQL 查询日志
SELECT greptime_timestamp, message, trace_id, log_level
FROM system_interaction_logs
WHERE greptime_timestamp >= $__fromTime
AND greptime_timestamp <= $__toTime
AND log_level = 'ERROR'
ORDER BY greptime_timestamp DESC
LIMIT 1000
步骤 5:设置数据生命周期(https://greptime.com/blogs/2026-06-22-xiaomi-factory-log-case#step-5-set-a-data-lifecycle)
生产日志通常只需要保留固定时间段以满足合规要求。使用 TTL 自动清理过期数据。根据自身合规要求设置保留期限,以下数值仅为示例:
ALTER TABLE system_interaction_logs SET 'ttl' = '30d';
删除操作在压缩期间异步执行,不会阻塞写入或查询。即使是非常大的表上的 TTL 也不会冻结系统。
经验教训(https://greptime.com/blogs/2026-06-22-xiaomi-factory-log-case#lessons-learned)
重复日志(https://greptime.com/blogs/2026-06-22-xiaomi-factory-log-case#duplicate-logs)
部署初期,日志出现重复,每行后面紧跟着一条完全相同的副本。原因出在 Promtail 侧:Logback 和 Promtail 同时采集了同一个日志文件,导致重复写入。
提示:如果发现重复日志,请先检查采集管道配置,而不是 GreptimeDB。
选择版本(https://greptime.com/blogs/2026-06-22-xiaomi-factory-log-case#choosing-a-version)
生产环境应使用稳定版本。部署期间,团队先运行了 v0.17,遇到了异常进程 CPU 使用率,火焰图中只显示内核定时器中断。回退到 v0.16 后问题解决。
提示:关注 GreptimeDB 的发布说明,并在测试环境中充分验证新版本后再上线。GreptimeDB 后续发布了 v1.0,进一步提升了稳定性。
监控 GreptimeDB 自身(https://greptime.com/blogs/2026-06-22-xiaomi-factory-log-case#monitor-greptimedb-itself)
GreptimeDB 暴露了 /metrics 端点,因此可以通过 Prometheus 采集其自身运行时指标,提前发现内存或 CPU 异常。官方提供了 Grafana 仪表板模板(https://github.com/GreptimeTeam/greptimedb/tree/main/grafana/dashboards/metrics/cluster)。在运行 v0.16 期间,团队遇到了一次 OOM 导致进程重启,监控指标及时暴露了问题。
TTL 语法注意事项(https://greptime.com/blogs/2026-06-22-xiaomi-factory-log-case#a-note-on-ttl-syntax)
设置 TTL 时,选项名称需要加引号:
-- 正确
ALTER TABLE system_interaction_logs SET 'ttl' = '30d';
-- 错误(会抛出错误)
ALTER TABLE system_interaction_logs SET TTL = '30d';
结果(https://greptime.com/blogs/2026-06-22-xiaomi-factory-log-case#results)
截至目前,小米智能工厂已在一个车间完成了系统交互日志解决方案的分阶段上线,其表现符合预期。
查询性能(https://greptime.com/blogs/2026-06-22-xiaomi-factory-log-case#query-performance)
- TraceID 查询:亚秒级响应,达到近乎瞬时的目标。
- 时间范围查询:跨小时级时间窗口的日志检索稳定。
- 全文搜索:高效的基于关键词的日志搜索。
存储效率(https://greptime.com/blogs/2026-06-22-xiaomi-factory-log-case#storage-efficiency)
GreptimeDB 的列式存储和压缩使得在数十亿行规模下仍能获得良好的存储效率,TTL 自动清理过期数据,无需手动维护。
运维体验(https://greptime.com/blogs/2026-06-22-xiaomi-factory-log-case#operational-experience)
- 与现有采集管道兼容:只需对 Promtail 配置进行最少更改。
- 自动 Schema 演进:新日志字段出现时无需手动修改表结构。
- 标准 SQL:降低查询学习曲线。
总结(https://greptime.com/blogs/2026-06-22-xiaomi-factory-log-case#conclusion)
在 GreptimeDB 上构建系统交互日志解决方案的关键步骤:
- 配置日志推送端点:Promtail 通过 Loki Push API 并带 Basic Auth 写入 GreptimeDB。
- 设计管道:编写 VRL 字段提取规则以匹配日志格式。
- 优化索引:根据查询模式为高基数字段添加跳过索引,并在需要更高速度时降低 granularity。
- 使用 SQL 查询:通过 GreptimeDB Grafana 插件以 SQL 检索日志。
更多阅读:
- GreptimeDB Loki 协议文档(https://docs.greptime.com/user-guide/ingest-data/for-observability/loki/)
- 管道配置指南(https://docs.greptime.com/user-guide/logs/pipeline-config/)
- 日志查询与索引(https://docs.greptime.com/user-guide/logs/fulltext-index-config/)
如果您也在考虑从 Loki 迁移,OceanBase Cloud 在更大规模上走了相同的道路:从 Loki 到 GreptimeDB Enterprise 的演变(https://greptime.com/blogs/2025-07-22-user-case-obcloud-log-management-greptimedb)—— 80+ 集群、300 TB 日志,日志存储成本降低 60% 以上。
感谢小米智能工厂研发团队在部署过程中的反馈与协作,帮助我们持续改进 GreptimeDB 的日志处理能力。
相似文章
@Greptime: GreptimeDB 的扁平格式查询现在可以在任何列上预过滤——标签、字段、时间戳——而不仅仅是主键。而…
GreptimeDB 的扁平格式查询现在支持在任何列(标签、字段、时间戳)上预过滤,而不仅仅是主键,性能提升高达 4.5 倍。此外,mito2 存储引擎移除了其遗留扫描路径,清理了约 1800 行代码。
@Greptime: 我们更新了对GreptimeDB内部存储引擎Mito2的深入解析,涵盖LSM-tree写入路径、列式Parquet SST等……
GreptimeDB的Mito2存储引擎采用LSM-tree设计,结合列式Parquet SST、三级扫描剪枝以及TWCS压缩。该博客文章对其架构进行了全面解析。
@Greptime: GreptimeDB 六月的大部分工作归结为一个想法:如果过滤器无法到达数据,那么它就没用。在分布式查询中…
GreptimeDB 通过启用远程动态过滤器在运行时下推到 datanode 扫描,并优化优化器使其在 MergeScan 包装远程计划之前运行,从而确保过滤器到达数据,提升了分布式查询性能。JSON v2 列现在支持类型提示。
@Greptime: DataFusion 在去年九月向上游合并了动态过滤下推功能。GreptimeDB v1.0 将其接入 Mito 扫描层。…
GreptimeDB v1.0 集成了 DataFusion 的动态过滤下推功能,通过将运行时边界推送到扫描层来加速 TopK 查询,在 50 亿行的 trace 表上将查询时间从 29 秒降低到 0.21 秒。
@LangChain:如何在支持对高达数百MB的代理轨迹进行全文搜索JSON过滤的同时,保持中位数(P50)延迟为400ms?
LangChain工程师详细介绍了他们如何为SmithDB从头构建自定义倒排索引,以支持对存储在对象存储中的大容量代理轨迹进行全文搜索和JSON过滤,尽管负载巨大,仍实现了400ms的中位延迟。