亲自动手体验 Elasticsearch:深入探索 Elasticsearch Labs 仓库 中的示例笔记本,开始 免费云试用,或者立即在您的 本地机器 上试用 Elastic。
经过一年对时间序列 数据流 (TSDS) 和 Elasticsearch 查询语言 (ES|QL) 的不懈努力,Elasticsearch 已转型成为一个指标数据存储,其在数据摄入、存储和查询性能方面,与 Prometheus、Mimir 和 ClickHouse 相比,表现持平甚至 更优。
Elasticsearch 存储 OpenTelemetry 指标的每个数据点现在仅需 3.75 字节,相比一年前的 25 字节大幅减少。索引吞吐量提升高达 50%。时间序列查询速度最高可达 160 倍。这就是 TSDS 和 ES|QL 一年工作所带来的成果:一个完全列式化的指标引擎,它能与您的日志、追踪和文档数据在同一平台上存储和查询 OpenTelemetry (OTel) 和 Prometheus 数据。如果您对详细的故事、架构细节和基准测试感兴趣,请阅读 我们如何将 Elasticsearch 重建为领先的列式指标数据存储。
本文将上述工作及背后的深入探究整合到了一处。以下是内容的快速概览。TSDS 是 Elasticsearch 用于指标的索引模式:在索引上启用它后,Elasticsearch 会将每个文档按其时间序列排序存储,将给定系列路由到单个分片,并应用针对指标的压缩,无需手动调优。ES|QL 是 Elasticsearch 的管道式查询语言,用于读取这些数据,并且通过这项工作,它将时间序列视为一等公民数据类型。以下所有内容都围绕着如何使 TSDS 占用更小的空间、存储更快,以及如何让 ES|QL 更高效地查询这些数据。
核心信息很简单:对于 TSDS,Elasticsearch 现在是一个完全列式指标引擎,这与大多数人想象的文档存储有所不同。同一个平台可以存储您的指标、日志、追踪和文档,并且 ES|QL 可以查询所有这些数据。
Elasticsearch 中的列式布局基于 TSDS 自 8.7 版本以来强制执行的四个属性:
_tsid,这是每个时间序列的唯一标识符。[_tsid 升序, @timestamp 降序] 排序,因此每个时间序列在磁盘上连续存放,并且维度值会聚类在一起。_tsid,因此给定系列存在于一个分片中。过去一年中的关键变化是停止为每个字段保留单独的倒排索引或 BKD 树,而是将每个字段作为 DocValues(Lucene 的列式存储)存储,并辅以 Doc Value Skippers,后者是轻量级的层次化稀疏索引。这使得磁盘布局端到端地列式化,从而允许查询引擎一次读取一列并进行向量化执行处理。
当大多数数据点都带有独特的维度集时(这在 OTel 和 Prometheus 数据中很常见),每个文档通常只包含一个数据点。这种设置最初每个 OTel 数据点占用 25 字节。以下四项改变使其降至 3.75 字节:
变更项 | 节省字节数 | 可用版本 |
|---|---|---|
Doc Value Skippers | -10 字节 | v9.3 |
更大的数值编解码块 | -2 字节 | v9.3 |
合成 _id | -5 字节 | v9.4 |
序列号截断 | -4 字节 | v9.4 |
总计 | -21 字节 (25 → 3.75) |
_tsid 和 @timestamp 排序,维度值在磁盘上聚类,Skippers 在其上表现良好,没有可测量的查询性能退化。Lucene 级别的机制在 Lucene 10 中的 DocValuesSkippers 如何使范围查询更快 中有详细介绍。自 9.3 版本以来,TSDS 默认启用 Skippers。_id(-5 字节)。 Elasticsearch 不再为 _id 构建倒排索引,而是从 _tsid 和 @timestamp 派生标识符,并使用段级布隆过滤器进行去重,仅在布隆过滤器命中时才回退到 Doc Values。文档 API 保持不变。其实现,包括布隆过滤器如何保持低误报率,在 Elasticsearch 如何通过合成 _id 和布隆过滤器削减时间序列存储 中有详细说明。在 9.4 版本中默认启用。_seq_no) 对于复制和乐观并发控制是必需的,但指标是只追加的,很少使用比较并交换更新。对于 TSDS,一旦全局检查点通过,序列号在段合并期间会被截断,这也消除了未来的合并工作。其权衡以及如何重新选择启用,在 Elasticsearch 如何通过在复制后丢弃序列号将指标存储减少 41% 中有所介绍。在 9.4 版本中普遍可用 (GA)。OTel 和 Prometheus 都以协议缓冲区 (protobuf) 形式发送指标。Elasticsearch 现在可以直接通过原生的 OpenTelemetry Protocol (OTLP) 和 Prometheus remote write 入口点接受这些二进制消息,而无需先将它们转换为批量请求。对于这两种协议,解析二进制数据比解析 JSON 更经济,_tsid 哈希在协调器上每个文档计算一次并在数据节点之间复用,并且维度哈希在一条消息中的多个数据点上分摊。结合 Doc Value Skippers 节省的索引 CPU 和 9.1 版本中添加的合成恢复源,OTel 索引吞吐量提高了高达 50%;由于 Prometheus remote write 复用相同的摄入路径,它也受益于这些优化。OTLP 入口点在 9.3 版本中达到 GA;Prometheus remote write 入口点在 9.4 版本中作为技术预览发布。
列式布局只有在查询引擎以列式方式读取时才能发挥作用。ES|QL 中的 TS 源命令以两级模型运行时间序列查询:每系列一次内部聚合(例如 RATE 或 AVG_OVER_TIME),然后是跨系列的外部聚合(例如 SUM 或 AVG)。由于数据是按 _tsid 顺序到达的,引擎会在获取的指标值列上应用内部函数,直到 _tsid 或时间桶发生变化,所有这些都通过向量化并行执行完成。
TS metrics
| WHERE TRANGE(1d)
| STATS SUM(RATE(search_requests)) BY host.name, TBUCKET(1h)在此模型之上,还叠加了几项优化:
_tsid 和维度值进行行程编码,并对空指标进行 Lucene 级别的过滤。_tsid 范围,以便在数据仍按顺序扫描时正确检测重置,并在时间桶边界处插值以获得准确的每桶差值。综合来看,这些优化使查询延迟比早期的 TSDS 版本提高了 160 倍。TS 和窗口支持在 9.4 版本中达到 GA。
ES|QL 中向量化的时间序列引擎(可提供高达 160 倍的查询性能)是您访问列式指标存储的方式。
时间序列支持于 9.2 版本作为技术预览版推出,包含 TS 命令,详见 9.2 ES|QL 更新。9.3 版本扩展了函数库并提高了延迟,详见 Elastic 的指标分析速度提升 5 倍:新增了 PERCENTILE_OVER_TIME、STDDEV_OVER_TIME、VARIANCE_OVER_TIME 和 DERIV 等用于分布和趋势分析的函数,CLAMP 用于限制嘈杂值,TRANGE 用于时间过滤,以及时间序列聚合上的滑动窗口参数。截至 9.4 版本,TS 命令及其时间序列聚合函数已达到 GA。有关完整参考,请参阅 TS 命令文档 和 时间序列聚合函数文档。
ES|QL 中的指标体验还包括以下三项功能:
exponential_histogram 字段类型直接存储 OTel 指数直方图,因此您可以在查询时以有界误差查询任何百分位数,无需固定桶也无损耗转换。::exponential_histogram 类型转换可以在同一查询中读取旧的 T-Digest 直方图数据。详细信息可在 ES|QL 中原生指数直方图支持 中找到。在 9.4 版本中达到 GA。METRICS_INFO 和 TS_INFO 命令会报告在当前查询上下文中实际拥有数据的指标和序列,包括它们的类型、单位和维度,而不是映射声明的所有字段。它们与相同的 TS 执行一起运行,并在数十亿文档上保持响应。有关更多详细信息,请查看 METRICS_INFO 和 TS_INFO 这篇文章。在 9.4 版本中达到 GA。由于所有这些都是 ES|QL,指标查询可以与语言的其余部分组合使用,包括 LOOKUP JOIN 和 INLINE STATS,这是仅支持 PromQL 的系统无法做到的。
对于已经构建了十多年 PromQL 查询和 Grafana 仪表板的团队来说,不应该为了获得 Elasticsearch 的所有优势而被迫重写它们。因此,Elasticsearch 现在端到端地支持 Prometheus:它通过 Prometheus remote write 摄入指标,并直接运行 PromQL 查询。
在摄入端,原生的 Prometheus remote write 端点无需适配器即可接受来自 Prometheus 或 Grafana Alloy 的 Snappy 压缩 protobuf,将标签映射到 TSDS 维度,并根据命名约定推断指标类型。其内部机制,从 protobuf 解析到数据流路由,在 Prometheus Remote Write 摄入在 Elasticsearch 中如何工作 中有详细介绍。由于 remote write 复用相同的存储和查询引擎,Prometheus 工作负载也能获得相同的存储和查询性能提升。
PROMQL 源命令直接在 ES|QL 内部运行 PromQL。它不使用单独的引擎:它解析 PromQL 表达式,将函数解析为对应的 ES|QL 等价物(例如,rate 对应 RATE,sum 对应 SUM 等),并构建一个 TS 执行计划,因此 PromQL 查询可以获得与原生 ES|QL 相同的向量化并行执行。
1 PROMQL sum(rate(http_requests_total))在 Kibana 中,该命令会从日期选择器推断 start、end 和 step,结果是一个常规的 ES|QL 表,您可以对其进行过滤、排序并通过 LOOKUP JOIN 进行丰富。完整设计在 在 Elasticsearch 中使用原生 PromQL 支持查询 Prometheus 指标 中有描述。
Prometheus remote write 和 PromQL 均在 9.4 版本中作为技术预览版提供。
目前有三个活跃的开发领域:
PromQL 覆盖范围和 Prometheus remote write 正在向 GA 迈进。
方向已定:一个平台,一个用于指标的列式引擎,无缝地存储和查询您的指标、日志和追踪。
立即开始 免费云试用,将您的 OTel 或 Prometheus 指标指向它,然后运行一个 TS 或 PROMQL 查询。
本文章中描述的任何功能或特性的发布和时间安排由 Elastic 自行决定。任何目前尚未提供的功能或特性可能不会按时交付或根本不会交付。
在 9.4 版本中,OTel 指标每个数据点仅需 3.75 字节,相比一年前的 25 字节大幅减少。这 6.6 倍的下降源于 TSDS 的四项改变:Doc Value Skippers、合成 _id、截断的序列号和更大的编解码器块。
对于 TSDS 指标来说,是的。每个指标和维度字段都作为 Lucene Doc Values 存储在自己的文件中,没有单独的倒排索引或 BKD 树。将这种磁盘布局与向量化的 ES|QL 引擎结合,您将获得端到端的列式存储和查询执行。
使用 TS 源命令,自 9.4 版本起已达到 GA。它会运行每个系列内部聚合(RATE、AVG_OVER_TIME 等)和跨系列外部聚合,所有这些都是向量化并行的。例如:TS metrics* | STATS SUM(RATE(search_requests)) BY host.name, TBUCKET(1h)。
可以,其中一种方式是通过 ES|QL 中的 PROMQL 源命令。它解析您的 PromQL,将函数映射到其 ES|QL 等价物,并构建一个 TS 执行计划,因此查询在与所有其他查询相同的引擎上运行。它在 9.4 版本中处于技术预览阶段,我们正在努力实现 PromQL 命令的全面覆盖。您还可以将任何 Prometheus 兼容客户端指向 Elasticsearch,并直接对您现有的指标运行 PromQL。
是的,两者都支持。OTel 指标直接通过 OTLP protobuf 端点(9.3 版本 GA)进入,Prometheus 指标通过原生 Prometheus remote write 端点(9.4 版本技术预览)进入,两种情况都无需适配器或批量转换。OTel 指数直方图也以 exponential_histogram 字段类型(9.4 版本 GA)原样存储,因此您可以在查询时请求任何百分位数。
复制分享
😔 毫无帮助
毫无帮助
😐 有点帮助
有点帮助
😁 非常有帮助
非常有用
报告问题
📡 更多 Elastic & AI 可观测性干货