继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

Easysearch ZSTD 基准测试:高压缩率下实现近 5 倍查询吞吐

极限实验室
关注TA
已关注
手记 110
粉丝 3
获赞 6

在搜索引擎领域,压缩算法的选择一直是一个经典的权衡难题:

  • 选择高压缩率(如 best_compression / DEFLATE),磁盘省了,但查询解压慢;

  • 选择高速编码(如默认 LZ4),查询快了,但磁盘占用大。

Easysearch 引入了基于 JDK 21 FFM(Foreign Function & Memory API) 直连本地 ZSTD 动态库的加速方案,试图打破这一困局。为了验证效果,我们在完全对等的环境下,对 Easysearch(ZSTD)和 Elasticsearch 7.10.2(best_compression)进行了一次严格的查询吞吐对比测试。

结果令人振奋——即使在系统明显背景负载下,Easysearch 也没有因为高压缩而变慢,反而在查询吞吐上实现了近 5 倍提升


测试环境

为确保对比公平,两套集群的硬件资源、JVM 配置、数据规模、索引结构完全对齐:

| 配置项 | Easysearch | Elasticsearch 7.10.2 |

| :--------------------- | :----------------------------------- | :----------------------------- |

| 节点数 | 3 | 3 |

| JVM 堆内存 | 12GB × 3 | 12GB × 3 |

| node.processors | 16 × 3 | 16 × 3 |

| 文档数 | 10,000,000 | 10,000,000 |

| 主分片 / 副本 | 3 / 0 | 3 / 0 |

| 数据类型 | nginx 访问日志 | nginx 访问日志 |

| 字段数 | 17 | 17 |

| mapping | 完全一致(MD5 校验) | 完全一致(MD5 校验) |

| Stored fields 压缩模式 | ZSTD (JDK21 FFM/native, level=3) | best_compression (DEFLATE) |

压缩机制对比:best_compression 映射到 Lucene BEST_COMPRESSION;在 stored fields 路径上,压缩实现为 DeflateWithPresetDictCompressionMode,内部使用 java.util.zip.Deflater/Inflater(即 DEFLATE)。

Easysearch ZSTD 当前走 JDK 21 FFM 绑定本地 zstd 库(java.lang.foreign);index.compression.zstd.jni=true 为当前这套实现的启用方式。

查询模型:JMeter 随机 match 查询,随机命中 service_namemethoderror_codeurl 四个字段,每次返回 10 条文档。

压测起始负载(_cat/nodes 快照):

| 负载项 | Easysearch run | Elasticsearch run |

| :---------- | :------------- | :---------------- |

| load_1m | 29.74 | 25.27 |

| load_5m | 27.10 | 28.15 |

| load_15m | 26.09 | 36.96 |

| ram.percent | 99 | 99 |

说明:压测并非在空闲机上进行,而是在已有明显背景负载的生产式环境下完成。


核心结果

1. 查询吞吐量(QPS):在高背景负载下,Easysearch 仍领先 372%

稳态阶段(3 轮平均),Easysearch 的查询吞吐是 Elasticsearch 的 4.7 倍

| 指标 | Elasticsearch (DEFLATE) | Easysearch (ZSTD) | 差异 |

| :-------------------------- | ----------------------: | ----------------: | :----------- |

| 稳态 QPS | 532.8 | 2,518.0 | +372.6% |

| 平均响应时间 | 779.0 ms | 164.3 ms | -78.9% |

| 稳态 CPU 占用(系统总占用) | 92.43% | 89.59% | 仅作背景参考 |

注:压测期间服务器存在明显背景负载(其他进程占用较高),该 CPU 指标是系统总占用,不等价于“仅搜索进程”的纯业务 CPU 对比。

在系统总 CPU 均接近 90% 的背景下,Easysearch 仍达到接近 5 倍吞吐。

2. 响应时间:从近 1 秒降到 164 毫秒

用户体感上,这意味着:同样一个搜索请求,Elasticsearch 还在等解压,Easysearch 已经把结果送到了客户端。

3. 各轮次详细数据

4. CPU 使用效率:每 1% CPU 产出的 QPS 差距惊人

单看 CPU 占用率,两者似乎差不多(89.59% vs 92.43%)。但如果换一个视角——每消耗 1% CPU 能产出多少 QPS,差距就一目了然了:

| 指标 | Elasticsearch (DEFLATE) | Easysearch (ZSTD) | 倍数 |

| :--------------- | ----------------------: | ----------------: | :-------- |

| 稳态 QPS | 532.8 | 2,518.0 | — |

| 稳态 CPU | 92.43% | 89.59% | — |

| QPS / 1% CPU | 5.76 | 28.10 | 4.88× |

这意味着什么?

  • ES 使用 DEFLATE(best_compression)时,解压路径更可能成为 CPU 热点;结合 ES 的高 CPU(92.43%)与较低 QPS,说明单位 CPU 产出偏低;

  • Easysearch 使用 ZSTD(JDK21 FFM/native)时,解压开销更小;在相近 CPU 水位(89.59%)下获得更高 QPS,单位 CPU 产出明显更高。

换句话说,当前这组实测更支持“ZSTD 在该查询模型下单位 CPU 产出更高”。

5. 存储空间:ZSTD 并未膨胀

| 索引 | 压缩算法 | 磁盘占用 |

| :----------------------- | :------------------------------- | -------: |

| nginx_best_10m (ES) | best_compression (DEFLATE) | 1.8 GB |

| nginx_zstd3 (Easysearch) | ZSTD (level=3, JDK21 FFM/native) | 1.9 GB |

两者存储空间接近。若按 _cat/indices 的 1 位小数展示是 1.8GB vs 1.9GB;若按 _stats/store 字节值计算,差异约 2.5%。因此可以认为 ZSTD 在 level=3 下与 DEFLATE best_compression 压缩率接近。


为什么 ZSTD 能做到"又小又快"?

传统认知中,压缩率和解压速度是一对矛盾。但 ZSTD 算法天然具备非对称压缩的特性:

在搜索引擎场景中,查询会触发存储字段(_source)读取与解压路径,命中文件系统页缓存时,可能不发生实际磁盘 I/O,但仍需进行 _source 解压。

当查询涉及较多 _source 读取时:

  • DEFLATE 的解压开销成为 CPU 瓶颈,拖慢了整体吞吐;

  • ZSTD(JDK21 FFM/native) 的解压速度在该场景下明显更优,单次请求的解压 CPU 成本更低,从而释放出更多 CPU 资源用于并发查询处理。

这就是为什么 Easysearch 在 CPU 占用更低(89.59% vs 92.43%)的情况下,反而能处理近 5 倍的查询量。


一张图总结


结论

Easysearch 的 ZSTD 压缩方案证明了一个事实:即使在高背景负载下,高压缩率和高查询性能依然可以兼得

在 1000 万条 nginx 日志、且系统存在明显背景负载的实测中:

  • 查询吞吐提升 372%,从 533 QPS 跃升至 2518 QPS

  • 平均响应时间下降 79%,从 779ms 降至 164ms

  • CPU 使用效率提升 388%,每 1% CPU 产出 28.10 QPS vs 5.76 QPS

  • CPU 占用绝对值下降 2.84 个百分点(相对下降约 3.07%)

  • 磁盘占用与 DEFLATE best_compression 接近(按字节口径约 +2.5%)

对于日志分析、可观测性、安全审计等需要兼顾存储成本和查询性能的场景,Easysearch ZSTD 是一个不需要妥协的选择。


ZSTD 使用方法

1) 新建索引时启用 ZSTD


curl  -k  -u  'admin:<password>'  -X  PUT  'https://127.0.0.1:9200/<index-name>'  \

-H 'Content-Type: application/json' -d '{

"settings":  {

"index.codec":  "ZSTD",

"index.compression.zstd.jni":  true

}

}'

可选参数:

  • index.compression.zstd.level(默认 3

说明:

  • index.compression.zstd.dict 固定为 true,无需单独配置

  • index.compression.zstd.dict 不作为独立开关来调整

2) 老索引切换到 ZSTD(推荐 reindex)

index.codec 是静态设置(打开状态不可动态改;可在关闭索引后调整)。

index.compression.zstd.jnifinal 设置(关闭索引后也不可修改)。

如果老索引要启用 index.compression.zstd.jni=true,建议新建目标索引后 reindex 迁移:

如果对已有索引执行 PUT /<index-name>/_settings 直接修改,会报错:final <index-name> setting [index.compression.zstd.jni], not updateable


# 先创建目标索引(启用 ZSTD)

curl  -k  -u  'admin:<password>'  -X  PUT  'https://127.0.0.1:9200/<target-index>'  \

-H 'Content-Type: application/json' -d '{

"settings":  {

"index.codec":  "ZSTD",

"index.compression.zstd.jni":  true

}

}'

  

# 再迁移数据

curl -k -u 'admin:<password>' -X POST 'https://127.0.0.1:9200/_reindex' \

-H 'Content-Type: application/json' -d '{

"source":  {  "index":  "<source-index>"  },

"dest":  {  "index":  "<target-index>"  }

}'

3) 校验是否生效


curl  -k  -u  'admin:<password>'  \

'https://127.0.0.1:9200/<index-name>/_settings?include_defaults=true&pretty'

重点确认:

  • index.codec = ZSTD

  • index.compression.zstd.jni = true


关于 Easysearch

INFINI Easysearch 是一个分布式的搜索型数据库,实现非结构化数据检索、全文检索、向量检索、地理位置信息查询、组合索引查询、多语种支持、聚合分析等。Easysearch 可以完美替代 Elasticsearch,同时添加和完善多项企业级功能。Easysearch 助您拥有简洁、高效、易用的搜索体验。

作者:张磊,极限科技(INFINI Labs)搜索引擎研发负责人,对 Elasticsearch 和 Lucene 源码比较熟悉,目前主要负责公司的 Easysearch 产品的研发以及客户服务工作。


相关文章:

打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP