测试 Elastic 领先、开箱即用的功能。深入了解我们的示例笔记本,开始免费云服务试用,或立即在您的本地计算机上试用 Elastic。
在为高并发工作负载调优 Elasticsearch 时,标准方法是最大限度地增加 RAM,将工作文档集保存在内存中,以实现低搜索延迟。因此,best_compression 很少被考虑用于搜索工作负载,因为它主要被视为 Elastic Observability 和 Elastic Security 用例中优先考虑存储效率的节省存储措施。
在本博客中,我们证明当数据集大小显著超出操作系统页面缓存时,best_compression通过减少 I/O 瓶颈来提升搜索性能和资源效率。
设置
我们的用例是一个运行在 Elastic Cloud CPU 优化实例上的高并发搜索应用程序。
- 数据量:约 5 亿份文档
- 基础架构:6 个 Elastic Cloud(Elasticsearch 服务)实例(每个实例:1.76 TB 存储 | 60 GB 内存 | 31.9 个 vCPU)
- 内存与存储比率:约 5% 的总数据集可存储在 RAM 中
症状:高延迟
我们观察到,当当前请求数在 19:00 左右激增时,搜索延迟显著恶化。如图 1 和图 2 所示,尽管每个 Elasticsearch 实例的流量峰值约为每分钟 400 个请求,但平均查询服务时间仍恶化至超过 60 毫秒。

图 1:Elasticsearch 实例每分钟的请求数在 19:00 刚过就达到了峰值,约为 400。

图 2:平均查询服务时间开始飙升,上升并持续保持在 60 毫秒以上。
在完成初始连接处理后,CPU 使用率保持相对较低,表明计算并非瓶颈。

图 3:初始跃升后,CPU 使用率保持相对较低。
查询量与页面错误之间出现了强相关性。随着请求增加,我们观察到页面错误比例上升,峰值约为每分钟 40 万次。这表明活跃数据集无法完全放入页面缓存。

图 4:页面错误次数很高,峰值约为每分钟 40 万次。
同时,JVM 堆使用率也显示正常且平稳。这排除了垃圾回收问题,并确认瓶颈在于 I/O。

图 5:堆利用率保持平稳。
诊断:I/O 瓶颈
系统存在 I/O 瓶颈。Elasticsearch 依赖操作系统页面缓存从内存提供索引数据。当索引过大而无法放入缓存时,查询会触发开销很大的磁盘读取。虽然典型的解决方案是水平扩展(添加节点/RAM),但我们希望先充分利用现有资源的效率改进。
解决方案
默认情况下,Elasticsearch 对其索引段使用 LZ4 压缩,在速度和大小之间取得平衡。我们假设,改用 best_compression (使用 zstd)会减少索引的大小。更小的占用空间使得更大比例的索引能够放入页面缓存,以微不足道的 CPU 增加(用于解压缩)换取磁盘 I/O 的减少。
为了启用 best_compression,我们使用索引设置 index.codec: best_compression 重新索引了数据。或者,也可以通过关闭索引、将索引编解码器重置为 best_compression,然后进行段合并,也可实现相同的结果。
结果
结果证实了我们的假设:存储效率的提高直接转化为搜索性能的大幅提升,而 CPU 利用率并未相应增加。
应用 best_compression 后,索引大小减少了约 25%。虽然低于在重复日志数据中观察到的减少幅度,但这 25% 的减少实际上将我们的页面缓存容量提升了相同的比例。
在下一次负载测试期间(从 17:00 开始),流量甚至更高,每个 Elasticsearch 节点的请求峰值达到每分钟 500 次。

图 6:负载测试大约在 17:00 开始。
尽管负载更高,但 CPU 利用率仍低于上一次运行。先前测试中较高的使用率可能是由于过多的页面错误处理和磁盘 I/O 管理开销所致。

图 7:CPU 使用率低于上一次运行。
至关重要的是,页面错误显著下降。即使在更高的吞吐量下,错误次数也稳定维持在每分钟低于 20 万次,而基准测试中的错误次数则超过 30 万次。

图 8:页面错误次数显著改善。
尽管页面错误结果仍然不太理想,但查询服务时间却减少了约 50%,即使在负载更重的情况下也保持在 30 毫秒以下。

图 9:平均查询服务时间小于 30 毫秒。
结论:为搜索启用 best_compression
对于搜索用例中数据量超过可用物理内存的情况,best_compression 是一个强大的性能调优工具。
应对缓存未命中的常规解决方案是通过扩展来增加 RAM。然而,通过减少索引占用空间,我们实现了相同的目标:最大化页面缓存中的文档数量。我们的下一步是探索索引排序,以进一步优化存储并从现有资源中获得更多性能。




