当 TSDS 遇到 ILM:设计不会拒绝延迟数据的时间序列数据流
作者来自 Elastic Bret WortmanTSDS 时间边界如何与 ILM 阶段交互以及如何设计能够容忍延迟到达 metrics 的策略。Elasticsearch 允许你以快速且灵活的方式对数据进行索引。你可以在云中免费试用或在本地运行以了解索引是多么简单。最近我将一位客户的 metrics 集群从 “全部在 hot tier” 迁移到 hot / cold / frozen 架构。这是我之前做过几十次的变更。然而几分钟之内Logstash 完全停止了数据推进。Elasticsearch 开始拒绝延迟到达的 metrics。这些拒绝导致 pipeline 落后从而产生更多延迟数据进而触发更多拒绝。最终pipeline 完全停滞。我们不得不从 snapshot 恢复重新索引数据并重新设计数据摄取 pipeline 才得以恢复。根本原因并不是 index lifecycle managementILM本身而是 time series data streamsTSDS以及它们如何对具有时间边界的 backing indices 进行约束。TSDS 可以将 metrics 的存储需求降低 40–70%但使 TSDS 高效的架构变化也改变了索引随时间的行为方式。在设计 ILM 策略或当你的摄取 pipeline 可能产生延迟到达的数据时这些变化非常关键。简而言之在使用 TSDS 时backing indices 只接受特定时间窗口内的文档。如果延迟数据在索引进入 cold 或 frozen 之后到达Elasticsearch 会拒绝这些文档或者在已配置的情况下将其路由到 failure store。设计规则warm_min_age rollover_max_age maximum_expected_lateness什么是时间序列数据流时间序列数据流TSDS是一种针对 metrics 数据优化的专用数据流。数据会被路由使相关文档位于同一分片中从而优化查询和检索。Elasticsearch 的实现方式如下每个文档包含一个 timestamp。用于标识时间序列的维度字段。表示测量值的指标字段。示例包括每个主机的 CPU 使用率。每个服务的请求延迟。每个传感器的温度读数。维度用于标识我们要测量的对象而指标表示随时间变化的值。维度维度描述被测量的实体。示例host.name service.name container.id我们在 mappings 中使用以下方式定义它们time_series_dimension: true指标指标表示数值型数据并使用以下方式定义time_series_metric常见的指标类型Gauge会上下波动的值。Counter持续增加直到重置的值。Elastic Agent 主要收集 metrics 和 logs 数据因此即使你没有手动启用任何 TSDS 索引你的集群中也可能已经存在它们。_tsid 字段Elasticsearch 会基于维度字段在内部生成 _tsid 值。这使得具有相同维度的文档可以被路由到同一个分片从而提升压缩率。查询局部性。聚合性能。关键区别有时间边界的 backing indices传统数据流始终写入最新的 backing index即 write index但 TSDS 的行为不同。每个 TSDS backing index 都有一个定义好的时间窗口只接受 timestamp 值落在该时间窗口内的文档GET _data_stream/my-metrics-data-stream { index_mode: time_series, time_series: { temporal_ranges: [ { start: 2026-01-15T14:35:50.000Z, end: 2026-03-16T11:34:40.000Z } ] } }当文档被索引时Elasticsearch 会将其路由到负责该 timestamp 的 backing index这意味着与传统索引不同TSDS 可能同时写入多个 backing indices。例如实时数据 → 最新索引。延迟数据 → 覆盖该时间范围的早期索引。为延迟到达的数据设计实际的摄取 pipeline 很少能按时完美交付 metrics。网络中断、途中积压、批量摄取以及边缘设备丢失后重新连接并开始补发都可能导致 metrics 延迟。传统索引会默默地吸收这些延迟而 TSDS 不会。如果文档的 timestamp 超出可写 backing indices 的范围Elasticsearch 会拒绝该文档这意味着你的 ILM 策略必须考虑延迟数据。关键约束Backing indices 必须保持可写状态足够长的时间以接受延迟数据。在实际操作中time_until_readonly maximum_expected_lateness因为 ILM 从 rollover 计算索引年龄操作规则变为warm_or_cold_min_age rollover_max_age maximum_expected_lateness例如如果 metrics 最多可能延迟六小时到达则索引在 rollover 后至少必须保持六小时可写。未考虑此约束正是之前导致摄取失败的原因。延迟到达的数据被定向到较早的索引而该索引已在 cold tier因此被写入阻止。处理被拒绝的文档当 TSDS 拒绝文档时Elasticsearch 会返回错误提示 timestamp 不在可写索引范围内。你的摄取 pipeline 如何处理该错误决定了你是丢失数据还是导致摄取停滞。处理被拒绝文档的主要机制是 failure store。Failure store在 Elasticsearch 9.1 推荐使用Elasticsearch 9.1 引入了 failure store它会自动捕获被拒绝的文档。Elasticsearch 不再将错误返回给客户端而是将失败的文档写入数据流内的专用 failure index。你可以使用以下方式检查失败文档GET metrics-myapp::failures/_search使用 failure store 可以防止摄取 pipeline 因拒绝错误而中断同时保留失败的数据以供分析或重新索引。监控拒绝问题延迟到达的问题通常最先表现为摄取异常。你可能会首先注意到索引速率突然下降。被拒绝文档的激增。failure store 条目的数量持续增长。pipeline 输入与输出计数不匹配。对这些信号设置告警可以让运维人员在 pipeline 停滞之前发现问题。可使用 workflows、机器学习任务以及其他机制来实现自动检测和通知。TSDS ILM 迁移清单如果你正在将 metrics 集群迁移到 TSDS、引入 ILM 分层或升级到默认使用 TSDS 的 Elasticsearch 版本请先检查以下内容。1测量摄取延迟在更改 ILM 策略之前确定正常的摄取延迟。事件期间的最坏延迟。批量 pipeline 引起的延迟。你的 ILM 设计必须考虑最大现实延迟。2验证索引时间窗口检查你的 TSDS backing indicesGET _data_stream/your-stream查看time_series.start_timetime_series.end_time这些边界决定哪些索引可以接受文档。理解这些时间窗口可以帮助你确定数据在被拒绝前可以延迟多久。3为延迟到达调整 hot tier 大小确保 backing indices 保持可写状态足够长以接收延迟数据。操作规则warm_min_age rollover_max_age maximum_expected_lateness记住如果 metrics 可能延迟六小时到达索引至少必须保持六小时可写。4决定如何处理被拒绝的文档在启用 TSDS 之前选择策略Failure store在 Elasticsearch 9.1 推荐使用Logstash dead letter queue延迟到达的备用索引接受有限的数据丢失5监控摄取健康状况为以下情况添加告警索引速率下降被拒绝的文档failure store 增长pipeline 输入/输出不匹配延迟数据问题通常最先表现为摄取异常。总结时间序列数据流为 metrics 工作负载提供了显著的存储和性能提升但它们引入了一个重要的架构变化backing indices 有时间边界这会影响 ILM 的行为。使用 TSDS 时索引必须保持可写状态足够长以接受延迟数据。摄取 pipeline 应安全处理被拒绝的文档。需要记住的关键规则是warm_min_age rollover_max_age maximum_expected_lateness如果你围绕该约束设计 ILM 策略TSDS 对 metrics 工作负载非常有效。如果忽略它你的摄取 pipeline 可能会以痛苦的方式发现这些时间边界。原文https://www.elastic.co/search-labs/blog/tsds-ilm-elasticsearch