如何使用 LogsDB 降低 Elasticsearch 日志存储成本

张开发
2026/4/11 16:50:57 15 分钟阅读

分享文章

如何使用 LogsDB 降低 Elasticsearch 日志存储成本
作者来自 Elastic Jeffrey Rengifo了解如何在 Elasticsearch 中启用 LogsDB 索引模式并衡量实际存储节省效果。我们将使用 Apache 日志对比标准索引与 LogsDB 索引并展示可以节省多少存储空间。LogsDB 是一种专门的 Elasticsearch 索引模式它以更低的存储成本提供完整功能。你的 Kibana 仪表板、搜索、告警和可视化都可以像以前一样正常工作不会丢失任何数据也不需要修改查询或工作流。只需一个配置就能让所有东西变得更便宜。在基准测试中LogsDB 将一个数据集从162.7 GB 降低到 39.4 GB—— 减少了 76% 的存储空间。你可以在 elasticsearch-benchmarks.elastic.co 查看完整的夜间基准测试结果。在本教程中你将使用 Kibana Dev Tools 和 Apache logs 数据集复现这个实验。你会创建两个完全相同的索引将相同的数据写入两个索引并使用 _stats API 测量存储差异。最终你会在测试数据上看到 44% 的存储减少并理解为什么在生产环境中节省幅度会更高。如果你已经在使用 Elasticsearch 9.2任何以 logs- 开头的数据流默认已经启用了 LogsDB。你可以直接跳到 “What about your existing logs?” 来验证你的配置。想了解完整背景关于这些节省背后的工程演进 —— 包括 Lucene doc values、synthetic _source、index sorting 和 ZSTD 是如何在十二年间逐步叠加实现的——可以参考 “Elasticsearch 多年来的发展LogsDB 如何将索引大小最多降低 75%”。前提条件Elasticsearch 8.17 集群、Elastic Cloud 部署或 Serverless具有 Dev Tools 访问权限的 Kibana一些日志数据对在 Kibana Dev Tools 中运行 API 调用有基本了解LogsDB 如何节省存储LogsDB 通过叠加三种机制来实现存储压缩索引排序Index sorting——按照 host.name 和 timestamp 对文档排序将相似日志行聚集在一起使压缩算法更容易找到重复模式。单这一项就能带来大约 30% 的节省。ZSTD 压缩 delta/GCD/运行长度编码——best_compression 会从 LZ4 切换到 Zstandard并对每个 doc values 列应用数值编码。本教程中的标准索引使用的是 LZ4因此你测量到的差异中有一部分来自 LogsDB 自动启用的完整优化组合。Synthetic _source——Elasticsearch 不再存储原始 JSON blob而是在需要时通过 doc values 重建 _source从而额外带来 20–40% 的存储节省。Synthetic _source 的权衡返回文档中的字段顺序可能与原始数据不同并且在多值数组字段的一些边缘情况下行为会有所差异。对于大多数日志分析工作负载这些差异是不可见的但在延迟敏感应用中启用前仍需参考 synthetic _source 文档。关于这些机制背后的架构细节可以查看 “Elasticsearch 多年来的发展LogsDB 如何将索引大小最多降低 75%”。接下来我们将一步步讲解如何启用 LogsDB 并测量存储节省效果。步骤 1使用 Elastic Agent 收集日志将 Apache 日志导入 Elasticsearch 的推荐方式是通过 Elastic Agent 并使用 Apache 集成。它可以自动处理采集、解析、ECS 字段映射以及路由。浏览 Elastic integrations 目录中的所有可用集成。一旦 Elastic Agent 开始收集日志并将其路由到 logs-apache.access-*就可以进入下一步。步骤 2创建两个索引本教程中的所有命令都在 Kibana Dev Tools 中运行。创建一个标准索引和一个 LogsDB 索引两者具有完全相同的字段映射。唯一的区别是 index.mode: logsdb。标准索引PUT /apache-standard { mappings: { properties: { timestamp: { type: date }, host.name: { type: keyword }, http.request.method: { type: keyword }, url.path: { type: keyword }, http.version: { type: keyword }, http.response.status_code: { type: integer }, http.response.bytes: { type: integer }, http.request.referrer: { type: keyword }, user_agent.original: { type: keyword } } } }LogsDB 索引PUT /apache-standard { mappings: { properties: { timestamp: { type: date }, host.name: { type: keyword }, http.request.method: { type: keyword }, url.path: { type: keyword }, http.version: { type: keyword }, http.response.status_code: { type: integer }, http.response.bytes: { type: integer }, http.request.referrer: { type: keyword }, user_agent.original: { type: keyword } } } }这一行index.mode: logsdb会自动启用所有三种存储机制。Elasticsearch 会在后台开启以下额外设置——你无需手动配置任何一项{ index.sort.field: [host.name, timestamp], index.sort.order: [asc, desc], index.codec: best_compression, index.mapping.ignore_malformed: true, index.mapping.ignore_above: 8191 }步骤 3重新索引日志使用 _reindex API 将相同的文档复制到两个测试索引中POST /_reindex { source: { index: logs-apache.access-* }, dest: { index: apache-standard } } POST /_reindex { source: { index: logs-apache.access-* }, dest: { index: apache-logsdb } }两个索引现在包含完全相同的文档因此下一步的存储对比只反映索引模式index mode的差异。步骤 4强制合并以确保公平对比在测量之前对两个索引执行 force merge将其合并为单个 segmentPOST /apache-standard/_forcemerge?max_num_segments1 POST /apache-logsdb/_forcemerge?max_num_segments1这些请求会阻塞直到合并完成。请等待两个请求都返回后再继续。为什么这一步很重要Elasticsearch 在写入数据时会先生成多个 Lucene segment并在后台逐步合并。如果在合并过程中进行测量会因为每个 segment 单独压缩而导致存储数据被高估。强制合并为单一 segment 可以展示索引在稳定状态下的真实存储占用这更接近生产环境中的最终表现。注意只有在索引不再写入时才应执行 _forcemerge。对仍在写入的索引执行 force merge 会消耗大量资源并可能影响 ingestion 性能。在生产环境中可以通过 Index Lifecycle ManagementILM在 warm 或 cold 阶段自动执行 force merge此时索引通常已经 rollover不再承载写入。步骤 5测量差异GET /apache-standard/_stats?filter_pathindices.*.primaries.store GET /apache-logsdb/_stats?filter_pathindices.*.primaries.storefilter_path 参数可以让响应更聚焦。请在每个响应中查看 primaries.store.size_in_bytes。在我们使用 Apache 日志数据的测试中结果如下索引文档数大小apache-standard111,81815.37 MBapache-logsdb111,8188.6 MB减少比例44%从这个角度来看在 1 TB 的日志数据下LogsDB 可以将其压缩到约 560 GB。这意味着在不修改任何查询的情况下节省了 450 GB。在生产规模数十亿文档并启用 synthetic _source下节省比例可达到 76%——在我们的基准测试中从 162.7 GB 降低到 39.4 GB。在 Kibana 中可视化要直观查看存储差异请打开 Kibana进入Management→Stack Management→Index Management。你会看到两个索引并排列出并显示各自的当前大小。为什么 Kibana 显示的数值比 _stats 更大Kibana Index Management 显示的是包含所有 replica shards 在内的索引总大小。而上面的 _stats 查询使用的是 primaries只报告 primary shards 的大小。无论采用哪种方式两种索引之间的比例关系是保持一致的。那你现有的日志呢Elasticsearch 9.2默认已启用从 9.2 开始任何匹配 logs-* 命名模式的数据流都会自动使用 LogsDB。你很可能已经在没有任何配置改动的情况下节省了存储空间。验证你现有的数据流GET /.ds-logs-*/_settings?filter_path*.settings.index.mode如果你在响应中看到index.mode: logsdb说明你已经在享受存储节省了。Elasticsearch 8.x 或 9.0–9.1通过 index template 为每个 data stream 启用在较早版本中需要通过更新 index template 来为 data stream 启用 LogsDB。此配置会影响所有由该模板创建的新索引——已有索引不会被修改因此迁移是安全且渐进的。选项 A —— 更新现有模板PUT _index_template/logs-myapp-template { index_patterns: [logs-myapp-*], data_stream: {}, template: { settings: { index.mode: logsdb } }, priority: 200 }选项 B —— 检查并修补现有的集成模板首先找到管理你数据流的模板GET _index_template/logs-apache*然后在 template.settings 代码块中添加 index.mode 设置使用 PUT _index_template/ 调用并包含完整的模板 body包括你新增的配置。更新模板之后下一个 rollover 生成的索引就会使用 LogsDB。如果你不想等待可以立即触发一次 rolloverPOST /logs-myapp-default/_rollover从 8.x 升级到 9.0现有的数据流不会被自动修改。只有新的 rollover 才会使用 LogsDB。不需要重新索引也不会有数据丢失——随着新的索引逐步滚动生成节省效果会逐渐累积。查询性能怎么样LogsDB 对于典型日志分析工作负载来说不会对查询性能产生显著影响。由于按照 host.name 和 timestamp 进行索引排序这在某些情况下反而能提升 range 查询和聚合性能因为匹配的数据会在磁盘上更紧密地存放在一起。对于不依赖这些字段过滤的查询其性能与标准索引基本一致。关于跨版本的索引写入吞吐性能数据可以参考配套文章中的 performance 部分。结论LogsDB 只需一个index.mode: logsdb配置即可启用并立即带来可观的存储节省在我们的实测中减少 44%在生产基准测试中启用 synthetic _source可达 76%162.7 GB → 39.4 GB。在 Elasticsearch 9.2 中所有 logs-* 数据流默认已启用 LogsDB。对于 8.x 或更早的 9.x 集群只需在 index template 中添加一行配置即可在下一次 rollover 生效无需重新索引也不会有数据丢失。下一步LogsDB index mode 文档Synthetic _source 文档与限制配置 logs data streamLogsDB 正式发布公告LogsDB 与 TSDS 性能基准测试原文https://www.elastic.co/observability-labs/blog/elasticsearch-logsdb-index-mode-storage-savings#next-steps

更多文章