Elasticsearch
【搜索客社区日报】第2318期 (2026-11-02)
社区日报 • Muses 发表了文章 • 0 个评论 • 223 次浏览 • 14 小时前
【搜索客社区日报】第2318期 (2026-11-02)
社区日报 • Muses 发表了文章 • 0 个评论 • 224 次浏览 • 15 小时前
【搜索客社区日报】第2315期 (2026-10-26)
社区日报 • Muses 发表了文章 • 0 个评论 • 1974 次浏览 • 2026-10-26 14:12
【搜索客社区日报】第2313期 (2026-10-19)
社区日报 • Muses 发表了文章 • 0 个评论 • 3651 次浏览 • 2026-10-19 15:17
【搜索客社区日报】第2274期 (2026-07-27)
社区日报 • Muses 发表了文章 • 0 个评论 • 10310 次浏览 • 2026-09-17 18:59
【搜索客社区日报】第2298期 (2026-09-14)
社区日报 • Muses 发表了文章 • 0 个评论 • 7854 次浏览 • 2026-09-14 07:37
【搜索客社区日报】第2296期 (2026-09-07)
社区日报 • Muses 发表了文章 • 0 个评论 • 10898 次浏览 • 2026-09-07 14:40
从国产替代到自主创新:极限科技亮相 DTCC 2026,分享 Easysearch 信创实践
Easysearch • INFINI Labs 小助手 发表了文章 • 0 个评论 • 11468 次浏览 • 2026-08-26 16:27
8月20–22日,第17届中国数据库技术大会(DTCC 2026)在北京朗丽兹西山花园酒店举行。本届大会由 IT168 联合 ITPUB 主办,以“融数聚智 创领未来”为主题,汇聚众多数据库领域专家、技术从业者与企业代表,围绕数据库内核、云原生、AI、向量数据库、实时数仓、分布式数据库及行业实践等热点展开深入交流。
在8月21日下午的【向量数据库技术实践】专场,极限科技 CEO 曾勇带来主题分享《从国产替代到自主创新:Easysearch 在搜索引擎领域的信创实践》,从 AI 时代搜索引擎的新定位出发,系统分享搜索引擎国产化面临的关键挑战,以及 Easysearch 在兼容迁移、企业级能力、信创适配、安全容灾和 AI 搜索等方面的实践探索。

一、AI 时代,搜索引擎正在从“工具”走向“基础设施”
过去,搜索引擎主要承担“找到信息”的任务,以关键词匹配、倒排索引、全文检索和 BM25 等技术为核心,服务于企业文档搜索、网站搜索、日志检索和数据查询等场景。
而随着大模型、RAG 和 Agent 快速发展,搜索正在发生新的变化。
从“匹配字面”走向“理解语义”,从“返回结果”走向“辅助决策”,搜索引擎正在成为连接企业数据与 AI 能力的重要基础设施。

在曾勇的分享中,他将这一变化概括为:
从“找信息”走向“用知识”。
如今,企业知识库、智能客服、运维诊断助手、合规审查,以及多模态搜索、Agent 自主搜索等应用,都离不开高质量的检索能力。搜索引擎也因此成为 RAG 和 Agent 获取知识、理解上下文的重要底座。
这也意味着,搜索引擎一旦从普通工具升级为企业 AI 基础设施,其稳定性、安全性以及自主可控能力的重要性将进一步提升。
二、国产替代,不能只是“换一个引擎”
随着信创建设持续深入,国产化正在从基础设施和外围系统逐步进入核心业务与数据基础设施领域。
在曾勇看来,搜索引擎国产化并不是简单完成一次产品替换,而是一项涉及业务连续性、数据迁移、技术自主、安全合规和长期演进能力的系统工程。

因此,在进行搜索引擎国产化选型时,至少需要重点关注五个方面:
- 自主可控:核心引擎和关键技术是否真正掌握在自己手中;
- 企业级稳定性:能否支撑 TB/PB 级数据、高并发和 7×24 小时稳定运行;
- 信创真实适配:能否真正适配国产 CPU、操作系统等基础环境;
- 安全治理能力:权限、审计、加密、脱敏等能力是否能够内建;
- 长期演进能力:能否持续支撑向量检索、AI 搜索、多模态搜索等未来需求。
归根结底,企业选择的并不仅仅是一套搜索软件,而是未来数年持续承载企业数据和 AI 应用的技术底座。
三、从“敢替”到“好用”,Easysearch 持续构建企业级搜索底座
围绕企业国产化过程中最关心的“怎么替、怎么迁、怎么回退、谁来服务、如何运维”等问题,极限科技持续围绕 Easysearch 完善从搜索引擎内核到企业级平台的完整能力体系。
作为企业级分布式搜索型数据库,Easysearch 支持非结构化数据检索、全文检索、向量检索、地理位置查询、组合索引查询、多语种搜索和聚合分析,并提供企业级安全与管理能力。

1. 兼容生态,让迁移更平滑
对于已经大规模使用 Elasticsearch 的企业而言,迁移成本往往是国产替代过程中最现实的问题之一。
针对这一挑战,Easysearch 持续强化兼容能力,覆盖 REST API、Java/Python/Go/Node.js SDK、Query DSL,以及 ES 6.x/7.x/8.x 数据读写,并兼容 Kibana、Logstash、Beats、Filebeat 等常见生态工具。同时针对龙芯、鲲鹏、飞腾以及麒麟、统信 UOS 等国产软硬件环境开展适配。
这意味着企业在推进国产化时,可以尽可能复用现有应用、技术栈和运维经验,降低迁移改造成本。
2. 企业级能力,让国产搜索真正“好用”
国产化的终点并不是“能够运行”,而是能够真正支撑企业核心生产业务。
Easysearch 从内核层面持续补齐企业级能力,包括 TLS 加密、RBAC/ABAC 权限控制、字段级脱敏、LDAP/AD 认证、IP 黑白名单、防暴力破解、磁盘及快照加密、限流限速、审计日志、文档级权限以及国密算法等能力。
在安全与容灾方面,Easysearch 支持 SM2、SM3、SM4 国密算法,并提供全量/增量 Snapshot 备份、备份文件加密、跨集群复制以及跨机房部署等能力,为金融、政务等高安全、高可靠场景提供基础支撑。
四、从全文检索到向量检索,为 AI 应用打好搜索底座
AI 时代,搜索引擎需要解决的不再只是“关键词能不能搜到”,还需要理解数据背后的语义。
Easysearch 已将全文检索、向量检索与混合搜索能力统一在同一引擎中,支持 kNN 向量检索、HNSW/LSH 等向量索引方式,并支持 BM25 全文检索与向量相似度的双路召回和融合排序。

通过统一搜索引擎承载全文、向量和混合检索,可以减少企业额外部署独立向量数据库带来的架构复杂度与运维成本,并进一步支撑语义搜索、RAG、Agent 长期记忆、企业知识库和多模态检索等场景。
这也是 Easysearch 从传统搜索基础设施向 AI Search Infra 演进的重要一步。
五、立足自主研发,持续深耕搜索基础设施创新
本次 DTCC 2026 的技术分享,是极限科技对国产搜索信创实践的一次集中输出。未来,极限科技将继续坚持自主创新路线,以 Easysearch 为基础,进一步完善企业级搜索、向量检索、AI 搜索和自主可控能力,推动搜索基础设施从“国产替代”走向“自主创新”,为企业数智化与 AI 应用发展构建更加安全、稳定、开放、可持续的搜索技术底座。
Bboss v7.5.6 正式发布,全面兼容国产分布式搜索引擎 Easysearch
资讯动态 • INFINI Labs 小助手 发表了文章 • 0 个评论 • 13693 次浏览 • 2026-06-23 23:31
一、引言
2026 年 6 月 21 日,经过 Bboss 开源社区与极限科技(INFINI Labs)的紧密合作, Bboss v7.5.6 正式发布!
作为国内领先的 AI 智能体开发框架、数据采集同步 ETL 工具以及流批一体化计算引擎,Bboss 在本次更新中与国产分布式搜索引擎 Easysearch 完成深度兼容,其 Elasticsearch Java 客户端 全面兼容 Easysearch 1.x、2.x 全系列版本。开发者现在可以无缝使用 Bboss 客户端操作 Easysearch 集群,享受与 Elasticsearch 一致的开发体验。

二、Bboss Elasticsearch 客户端简介
Bboss 是一款高性能、高兼容性的搜索引擎 Java REST 客户端框架,基于 Apache License 2.0 开源,原生支持 Elasticsearch、Easysearch 和 Opensearch。
自带客户端集群节点负载均衡和容灾,多集群多数据源,自动索引托管,多种分页机制,傻瓜级 CRUD,脚本,SQL,JDBC,高亮,权重,聚合,IP,GEO 地理位置,父子嵌套,应有尽有。
核心特性
| 特性 | 说明 |
|---|---|
| 原生多引擎支持 | 完美支持 ES 1.x ~ 9.x、Easysearch 1.x ~ 2.x、Opensearch 1.x ~ 3.x |
| 学习成本低 | 无需学习额外 API,只需掌握 Elasticsearch DSL,极简使用方式 |
| 开箱即用 | Spring Boot 自动配置,无需复杂设置 |
| 高效异步处理 | 内置 BulkProcessor 异步批处理器,大幅提升写入性能 |
| 灵活查询方式 | 支持 DSL、SQL、O/R Mapping 多种查询模式 |
| 多数据源支持 | 一个应用可同时操作多个不同版本的搜索引擎集群 |
| 客户端负载均衡 | 默认启用客户端负载均衡,容灾性更好 |
| 完整的结果封装 | 返回结果支持 JSON、PO 对象、List 集合、Map 等多种类型 |
三、为什么选择 Bboss + Easysearch
将 Bboss 作为 Easysearch 的 Java 客户端,您将获得以下独特优势:
- 国产化技术栈:从底层搜索引擎到上层客户端框架,完全国产化自主可控,满足信创合规要求,无许可证风险。
- 极低迁移成本:如果您正在使用 Elasticsearch + Bboss 技术栈,切换到 Easysearch 几乎零成本,只需修改连接配置即可。
- 成熟稳定的客户端:Bboss 经过多年发展,已在国内众多企业和项目中得到广泛应用和验证,拥有活跃的中文社区和完善的文档支持。
- 丰富的生态能力:除了基础的 CRUD 操作,还提供数据采集 ETL、流批一体化计算、AI 智能体等丰富的扩展能力。
四、快速开始
通过以下简单步骤,即可在 Bboss 中接入 Easysearch:
1. 添加 Maven 依赖
<dependency>
<groupId>com.bbossgroups.plugins</groupId>
<artifactId>bboss-datatran-jdbc</artifactId>
<version>7.5.6</version>
</dependency>
2. 配置 Easysearch 连接
spring:
elasticsearch:
bboss:
elasticsearch:
rest:
hostNames: localhost:9200
useHttps: true # Easysearch 默认启用 HTTPS
elasticUser: admin
elasticPassword: your_password
3. 基础操作
@Service
public class DocumentService {
@Autowired
private BBossESStarter bbossESStarter;
// 插入文档
public void insertDocument() {
ClientInterface client = bbossESStarter.getRestClient();
Document doc = new Document();
doc.setId("1");
doc.setTitle("Easysearch 与 Bboss 集成");
doc.setContent("这是一篇关于集成的文章");
client.addDocument("documents", doc, "refresh=true");
}
// 查询文档
public Document getDocument(String id) {
ClientInterface client = bbossESStarter.getRestClient();
return client.getDocument("documents", id, Document.class);
}
// 按字段查询
public ESDatas<Document> searchByAuthor(String author) {
ClientInterface client = bbossESStarter.getRestClient();
return client.searchListByField(
"documents", "author.keyword", author,
Document.class, 0, 10
);
}
}
五、结语
Bboss v7.5.6 与 Easysearch 的深度兼容,是国产开源生态建设的又一重要成果。作为 Easysearch 原厂,我们欢迎更多像 Bboss 这样的优秀开源项目加入国产搜索引擎生态,共同推动国内搜索型数据库的发展与繁荣。
对于正在评估搜索引擎选型或计划进行国产替代的企业用户,Bboss + Easysearch 的组合无疑是值得信赖的选择。
立即体验 Easysearch,开启国产搜索引擎之旅:
- Easysearch 官网: https://easysearch.cn
- Bboss 官方文档: https://esdoc.bbossgroups.com
- Easysearch x Bboss 详细集成文档: https://docs.infinilabs.com/easysearch/main/docs/integrations/third-party/bboss
六、关于 Easysearch

INFINI Easysearch 是一个分布式的搜索型数据库,实现非结构化数据检索、全文检索、向量检索、地理位置信息查询、组合索引查询、多语种支持、聚合分析等。Easysearch 可以完美替代 Elasticsearch,同时添加和完善多项企业级功能。作为国内领先的国产搜索引擎产品,Easysearch 具备以下核心优势:
1. 国产化自主可控
自主研发,符合信创要求,无许可证风险,为企业提供安全可靠的技术保障。在当前国际形势日益复杂、信创需求持续提升的大背景下,Easysearch 为政府、金融、电信、能源等关键行业提供了值得信赖的搜索引擎基础设施。
2. 轻量级架构
相比传统搜索引擎,Easysearch 资源占用更少,启动更快速,显著降低企业运维成本。其精简的架构设计使得在同等硬件条件下可以承载更多的业务负载,特别适合资源受限的私有化部署场景。
3. 卓越性能表现
查询性能优异,能够满足大部分业务场景需求,用户体验流畅。通过持续的内核优化和算法改进,Easysearch 在多项基准测试中展现出媲美甚至超越同类产品的性能水平。
4. 良好兼容性
与 Elasticsearch 的 API 接口基本兼容,迁移成本较低,保护用户现有投资。这一特性使得基于 Elasticsearch 开发的应用可以快速平滑地迁移至 Easysearch,大大降低了国产替代的技术门槛。
社区福利
为感谢广大社区开发者的支持,Bboss 与 Easysearch 厂商极限科技联合发起抽奖活动,奖品为开源T恤。6 月 29 日上午 10 点自动开奖,欢迎大家扫码抽奖参与。
Elasticsearch 6/7/8 到 Easysearch 2.x 迁移指南
Easysearch • INFINI Labs 小助手 发表了文章 • 0 个评论 • 11731 次浏览 • 2026-06-04 14:14

最近在协助客户进行 Elasticsearch 到 Easysearch 的迁移时,发现大家最关心的问题是"当前版本能否直接使用快照迁移"。这个问题看似简单,但不同版本的答案差异较大。本文将基于实际测试经验,梳理各版本的迁移路径和注意事项。
迁移路径速览
根据源 ES 版本,可以直接对照下表选择迁移方案:
| 源 ES 版本 | 能否直接快照恢复 | 推荐方案 | 实施复杂度 |
|---|---|---|---|
| ES 6.x | 否 | INFINI Gateway 迁移 或 ES 7.10.x 中转 | 较低 |
| ES 7.0 - 7.11 | 是 | 直接快照恢复 | 较低 |
| ES 7.12 - 7.17 | 否 | INFINI Gateway 迁移 | 较低 |
| ES 8.x | 否 | INFINI Gateway 迁移 | 较低 |
结论:ES 7.0-7.11 是迁移最顺畅的版本窗口,可直接快照恢复;其他版本也有成熟的迁移方案,只是路径不同。
版本差异的原因
迁移路径的差异主要源于两方面:Lucene 版本兼容性和快照元数据格式变化。
Lucene 兼容性:Easysearch 2.x 底层要求的最低 Lucene 版本对应 ES 7.0.0。ES 6.x 的索引文件使用老版本 Lucene,直接恢复会报错:
The index was created with version [6.8.23] but the minimum compatible version is [7.0.0].
快照元数据格式:ES 7.12 开始在快照中引入 uuid、cluster_id 字段,7.14 增加 writer_uuid,8.x 又引入 transport_version。这些字段与 Easysearch 2.x 的快照解析器不兼容。
因此,ES 7.0-7.11 成为迁移的"黄金窗口"——既满足 Lucene 兼容性要求,快照格式又足够简洁。
ES 7.0-7.11:直接快照恢复
这是测试最充分的迁移路径,已验证版本包括 ES 7.0.1、7.8.1、7.10.2 OSS、7.11.2。
已验证能力:
- 单索引 / 多索引 / 通配符批量恢复
- 常见字段类型与别名
- 自定义 settings、多分片索引
- ILM 托管索引、数据流后备索引、冻结索引
操作步骤:
# 1. 源 ES 创建快照
PUT /_snapshot/my_backup/snapshot_1
{
"indices": "索引列表",
"include_global_state": false
}
# 2. Easysearch 注册同一快照仓库
PUT /_snapshot/my_backup
{
"type": "fs",
"settings": {
"location": "/path/to/snapshot/repo",
"readonly": true
}
}
# 3. 恢复快照
POST /_snapshot/my_backup/snapshot_1/_restore
{
"indices": "索引列表",
"include_global_state": false
}
ES 6.x:Gateway 迁移或中转方案
ES 6.x 无法直接快照恢复到 Easysearch 2.x,有两种迁移方案可选:
方案一:INFINI Gateway 迁移(推荐)
直接使用 Gateway 从 ES 6.x 迁移数据到 Easysearch,无需中转集群。Gateway 已验证支持 ES 6.8.x 的数据迁移。
方案二:ES 7.10.x 中转
ES 6.8 -> 快照 -> ES 7.10.x -> 快照 -> Easysearch 2.x
ES 7.10.x 可以正常恢复 ES 6.x 的快照,恢复完成后再创建快照供 Easysearch 使用。该方案数据完整性有保障,但需要额外的中转存储和迁移窗口。
ES 6.x 特有字段:ES 6.x 的 string 类型在 Easysearch 中需映射为 text 或 keyword(根据实际使用场景选择)。
ES 7.12+ 和 8.x:INFINI Gateway 迁移
这两个版本段的快照格式与 Easysearch 2.x 不兼容,推荐使用 INFINI Gateway 进行迁移。Gateway 是 INFINI Labs 提供的数据迁移工具,专门针对 Elasticsearch 到 Easysearch 的迁移场景进行了优化。
架构示意
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Elasticsearch │ ──── │ INFINI Gateway │ ──── │ Easysearch │
│ (源集群) │ │ (迁移工具) │ │ (目标集群) │
└─────────────────┘ └─────────────────┘ └─────────────────┘
Gateway 内部通过 Scroll API 从源集群分批拉取数据,再通过 Bulk API 写入目标集群,整个过程对业务透明。
主要优势
- 配置简单:只需配置源集群和目标集群地址、索引名称即可
- 断点续传:支持从断点恢复,避免网络抖动导致重头再来
- 进度可视:实时显示迁移进度和速率
- 多索引并行:支持同时迁移多个索引
基本步骤
- 在目标集群创建索引的 mapping 和 setting
- 准备 Gateway 配置文件,填写源集群和目标集群连接信息
- 运行 Gateway 执行迁移
- 迁移完成后进行数据校验
详细的配置说明和操作示例,可参考 ES 数据迁移之 INFINI Gateway。
备选方案
如果需要更灵活的控制,也可以自行编写脚本,通过 Scroll API 读取源数据、Bulk API 写入目标。这种方式适合有定制化需求的场景,但需要自行处理断点续传、错误重试等逻辑。
字段类型兼容性
直接兼容类型:text、keyword、long、double、boolean、date、object、nested、geo_point、geo_shape、ip、completion、wildcard、flattened、alias、join、rank_feature、rank_features、integer_range、long_range、date_range、match_only_text 等。
ES 7.x / 8.x 需替换类型:
| ES 类型 | Easysearch 替代方案 | 数据保留 | 说明 |
|---|---|---|---|
dense_vector |
knn_dense_float_vector |
是 | 需安装 knn 插件,向量数据格式兼容 |
knn_vector |
knn_dense_float_vector |
是 | 需安装 knn 插件 |
sparse_vector |
knn_sparse_bool_vector |
是 | 需安装 knn 插件 |
constant_keyword |
keyword |
是 | 需手动维护常量值 |
runtime |
移除或转为普通字段 | 是 | Easysearch 不支持运行时字段 |
histogram |
object |
是 | 聚合 histogram 功能丢失 |
aggregate_metric_double |
object |
是 | 需手动计算聚合 |
unsigned_long |
long 或 keyword |
是 | 注意数值范围 |
semantic |
暂不支持 | - | ES 专有 AI 功能 |
向量迁移要点:ES 的 dense_vector 数据可直接迁移到 Easysearch 的 knn_dense_float_vector,数据格式 [0.1, 0.2, ...] 完全兼容。需预先在目标索引创建正确的 mapping。
建议迁移前先用小索引测试,确认 mapping 无问题后再全量迁移。
常见问题与避坑指南
1. include_global_state 参数设置
该参数控制是否恢复集群级配置(模板、ILM 策略等)。不同版本的情况:
| ES 版本 | 发行版 | global_state | 说明 |
|---|---|---|---|
| 7.0-7.7 | 任意 | 兼容 | 无 _index_template API |
| 7.8-7.10 | OSS | 兼容 | 无内置 _index_template |
| 7.8-7.10 | default | 可能不兼容 | 取决于是否使用 _index_template |
| 7.11+ | 任意 | 不兼容 | 有 9 个内置 _index_template |
建议:迁移时统一使用 include_global_state=false,先恢复数据再重建配置。
2. ILM 和 data stream 迁移
- ILM:索引的 lifecycle 设置保留,但 policy 需在 Easysearch 中重建
- 数据流 (data stream):后备索引 (backing index) 数据完整恢复,语义需在目标侧重建
- 冻结索引 (frozen index):自动恢复为普通可访问状态
3. 迁移验收标准
建议至少完成三项验证:
- 文档量一致
- 关键查询结果一致
- 核心业务链路压测通过
4. 迁移窗口规划
- 快照方案通常需要短停机窗口完成切换
- Gateway 迁移可实现近实时同步,仅在切换连接时短暂停服
快照格式变化参考
| 字段 | ES 7.0-7.11 | ES 7.12-7.17 | ES 8.x | Easysearch 2.x |
|---|---|---|---|---|
min_version |
7.9.0 或无 | 7.12.0 | 7.12.0 | 支持 |
uuid(仓库级) |
无 | 有 | 有 | 不支持 |
cluster_id |
无 | 有 | 有 | 不支持 |
writer_uuid |
无 | 有(7.14+) | 有 | 不支持 |
transport_version |
无 | 无 | 有 | 不支持 |
总结
本文梳理了 Easysearch 2.x 对 ES 6/7/8 的迁移路径:
- ES 7.0-7.11:直接快照恢复,路径最短
- ES 6.x:INFINI Gateway 迁移 或 ES 7.10.x 中转
- ES 7.12+ / 8.x:使用 INFINI Gateway 迁移
建议在正式迁移前,先选择非核心索引进行小规模验证,确认数据完整性和业务兼容性后再扩大迁移范围。
如有迁移相关问题,欢迎联系我们。
【搜索客社区日报】第2237期 (2026-05-25)
社区日报 • Muses 发表了文章 • 0 个评论 • 10608 次浏览 • 2026-05-25 14:43
【搜索客社区日报】第2231期 (2026-05-15)
社区日报 • Fred2000 发表了文章 • 0 个评论 • 13687 次浏览 • 2026-05-15 10:19
Easysearch analysis-ik 多词典性能优化:从性能回退到分词性能提升 25%~30%
Easysearch • INFINI Labs 小助手 发表了文章 • 0 个评论 • 16446 次浏览 • 2026-05-08 14:34
Easysearch 版 analysis-ik 相比开源 IK 有一个重要的增强:支持多词典。简单说就是不同字段可以挂不同词库,可以叠加默认词典,也可以只用自定义词典。这是开源单词典 IK 做不到的。
功能实现初期,主要精力放在把能力跑通上。但在后来的一次写入压测中,我们发现 Easysearch 的写入吞吐和 Elasticsearch 有明显差距,最终定位到问题出在多词典的实现方式上——字段最终该用哪套词典,本来应该在分词前就算好,结果代码里把这个选择丢进了分词的热路径,每次分词都要反复切词典、重复扫同一段文本。
这篇文章记录的就是我们怎么一步步把性能拉回来、最终反超基线的过程。
问题怎么冒出来的
4 月 20 号,我们跑了一轮系统级写入压测。数据、mapping、settings、并发和 bulk 参数都一样,Elasticsearch 8.19.5 和 Easysearch 2.1.2 的写入吞吐差距大得有点不对劲:
| 时间 | 场景 | Elasticsearch | Easysearch | 说明 |
|---|---|---|---|---|
| 2026-04-20 第 2 次有效重跑 | 29900 docs / bulk=250 / concurrency=3 端到端写入压测 |
129.44 docs/s |
31.21 docs/s |
这是整条写入链路的 docs/s,不是单独分词吞吐 |
| 2026-04-20 诊断样本 | 5000 docs / bulk=250 / concurrency=3 |
156.25 docs/s |
30.67 docs/s |
Easysearch 的累计索引耗时约为 Elasticsearch 的 8.0x |
当时服务器上跑的就是早期多词典版本。后面修性能,追的就是这个版本和开源单词典 IK 基线之间的差距。
这一步还不能直接确定问题就在分词器。但差距摆在这儿了,得继续往下排。我们先排除了几个常见干扰因素:
refresh_interval- 动态同义词 HTTP 服务
- mapping / settings 不一致
- 网络层和 bulk 客户端本身
采样结果很快把范围收窄了。Elasticsearch 那边热点比较分散,Easysearch 这边呢,分词链路里出现了异常集中的开销——分词过程中反复做词典选择和字典查找。
瓶颈不在 Lucene 写入链路本身,就在 analysis-ik 的多词典实现上。
根因分析
第一类问题出在实现模型上。多词典想表达的是”这个字段最终用哪套词典”,这件事完全可以在分词前算好。但早期代码里,硬是把它变成了运行时的事:
- “字段用哪个词典”变成了”运行时多轮扫描”——同一段文本对着多套词典各来一遍。
- 全局字典切换的动作放进了每字符的热路径。
- 结果就是同一段文本的扫描和查找成本翻了好几倍。
所以问题不是多词典天然慢,是实现把本该提前算好的东西塞进了热路径反复做。
第二类问题是后续优化过程中留下的额外开销。后面加的跨边界、停用词、长文本等测试本身不是性能问题的来源,它们的作用是把正确性边界补齐,确保每次优化不会改变分词结果。
最后通过性能分析确认,残留开销主要来自两处:缓存命中前还在做不必要的数据复制;诊断逻辑在生产热路径上产生了额外开销。修完之后这两处热点都从火焰图上消失了,说明性能回退确实来自真实的代码路径成本,不是测试抖动。
修复过程
整个修复分四个阶段。
第一阶段:把多词典从”运行时分发”收敛为”最终有效词典视图”
多词典能力保留,但不再让分词器在热路径里反复切词典、重复扫文本。改成在分词前就把字段最终生效的词典算好,分词过程只面对一个已经收敛好的词典视图。
说白了就是把模型拉回正确方向——多词典管表达能力,热路径只管分词。
第二阶段:逐步打掉热路径上的常数开销
留下来的每一项优化,都经过正式性能测试和采样分析验证。原则就一条:不改分词语义,只减少热路径上反复发生的查找、分配和判断。
第三阶段:补齐正确性护栏
正确性测试必须先到位,不然吞吐提升没有意义——万一分词结果变了,跑得再快也白搭。
这一轮重点覆盖了这些容易出问题的场景:
- 真跨边界场景
- 数字和量词合并,如
1号 - 自定义词典里的含符号词
- 补充平面字符跨边界稳定性
- 停用词过滤后的偏移量
- 长文本样本的稳定性
- 正式性能测试数据集的分词结果对齐
后面所有的吞吐数字,前提都是分词结果一致,避免把分词行为的变化误当成性能提升。
第四阶段:清理最后的残留开销
到 4 月 28 号,最后一轮修复集中处理两个地方:
- 词典视图命中缓存时直接返回,不再多做一次数据复制
- 诊断逻辑默认关掉,不让线上请求为调试能力买单
这两处修完,Easysearch 版 IK 就不只是恢复到单词典版本附近了,在正式测试里已经明显领先。
用数据看恢复过程
为了不把系统级写入压测和分词器性能测试混在一起,下面只看几个关键节点。2026-04-20 的 docs/s 是系统级写入吞吐,后面的 tok/s 是单独的分词器吞吐。
这里说的”开源 IK 基线”就是开源 IK 的单词典实现对照版本。所有正式吞吐结论都建立在同一数据集、同一测试方法、分词结果一致的前提上。
| 时间 | 口径 | 关键结果 | 说明 |
|---|---|---|---|
| 2026-04-23 17:02 CST | 初期本地复现 | 服务器多词典版本 61.39 万 tok/s,单词典版本 114.48 万 tok/s |
单词典版本快 86.49%,性能差距被明确复现 |
| 2026-04-24 09:51:12~09:55:15 CST | 第一次正式追平 | smart 相对开源单词典基线 +7.26% |
从明显落后追到略微领先 |
| 2026-04-25 04:14~04:16 CST | 双模式阶段复核 | smart +16.88%,max_word +20.09% |
领先优势开始扩大 |
| 2026-04-28 12:30:56 CST | 最新正式复核 | smart +30.96%,max_word +21.31% |
当前最新结果 |
整个过程就是:
- 先暴露出明显的性能退化
- 逐步缩小差距
- 追平,然后开始领先
- 最终在分词结果完全一致的前提下,正式反超
最早的本地复现数据很关键:服务器当时跑的多词典版本只有 613896.67 tok/s,单词典版本 1144843.77 tok/s。后面所有修复就是冲着这个差距去的。
三张图分别对应问题暴露、分词复现和修复结果:第一张展示服务器 bulk 写入吞吐的系统级差距;第二张展示多词典版本和单词典版本的本地分词差距;第三张展示分词结果对齐后,Easysearch 版 IK 怎么一步步追上来,最终实现 25%~30% 的分词性能提升。
为什么说 Easysearch 版 IK 现在更好
这次修复的价值不只是消灭了几个热点,更重要的是把多词典能力、分词正确性和性能测试体系一起补齐了。
1. 功能更强,性能代价可控
开源单词典 IK 模型简单,但表达能力也弱。Easysearch 的多词典能力要解决的是字段级词库隔离、自定义词典叠加这些实际需求。
关键问题是:能不能把这些能力的性能开销压到足够低。修复后的结果证明,可以。
2. 正确性护栏更完整
这轮补上的测试不只是几个短样例,覆盖了更容易翻车的边界条件:
- 真跨边界场景
- 长文本稳定性
- 自定义词典和符号词
- 数字量词合并
- 停用词过滤后的偏移量
这意味着以后再做性能优化,必须同时保证分词结果不变。想靠改分词行为换吞吐,测试会先拦住。
3. 性能测试体系更严格
这轮之后,Easysearch 对 analysis-ik 的正式性能结论统一按一套标准出:
- 同一数据集
- 同一测试方法
smart和max_word双模式- 分词结果一致
- 有性能分析结果支撑
这套体系能避免两个常见坑:只看单轮吞吐波动就下结论,或者分词结果已经变了还在比性能。
小结
多词典能力在实现初期,主要精力放在功能补齐上——先把字段级词库隔离、自定义词典叠加这些能力跑通,性能优化是后面分阶段来的事,没办法一蹴而就。
这轮优化下来,核心思路其实就一条:把词典选择从分词热路径里挪出去,提前收敛好,让分词过程只面对最终的词典视图。再配合热点清理和正确性护栏,增强功能和更高性能完全可以兼得。
截至 2026 年 4 月 28 日,在本地 Mac 笔记本上的多轮 benchmark 中,Easysearch 版 IK 在 smart 模式大约领先开源单词典 IK 基线 25%~30%,max_word 模式大约领先 20% 左右,分词结果完全一致。具体数字每次跑会有波动,但趋势是稳定的。
这也是 Easysearch 版 IK 相对开源版更有价值的地方:不是多了几个配置项,而是在多词典能力、分词正确性和分词性能三个方面都给出了可验证的结果。
关于 Easysearch

INFINI Easysearch 是一个分布式的搜索型数据库,实现非结构化数据检索、全文检索、向量检索、地理位置信息查询、组合索引查询、多语种支持、聚合分析等。Easysearch 可以完美替代 Elasticsearch,同时添加和完善多项企业级功能。Easysearch 助您拥有简洁、高效、易用的搜索体验。
作者:张磊,极限科技(INFINI Labs)搜索引擎研发负责人,对 Elasticsearch 和 Lucene 源码比较熟悉,目前主要负责公司的 Easysearch 产品的研发以及客户服务工作。
相关文章:
Easysearch BKD Merge 异常排查实录:最终定位到旧版 GraalVM JIT 运行时
Easysearch • INFINI Labs 小助手 发表了文章 • 0 个评论 • 12087 次浏览 • 2026-04-10 17:51
最近一次高并发写入压测中,我们遇到了一个非常诡异的 BKD merge 崩溃。从报错看,很像 Easysearch 2.1.2 在 merge 阶段把 segment 读成了错误状态。典型错误是这样的:
java.lang.ArrayIndexOutOfBoundsException: Index -3 out of bounds for length 8
java.lang.ArrayIndexOutOfBoundsException: Index -4 out of bounds for length 8
异常栈最终落在 Lucene BKD 相关路径上:
BKDReader.readNodeData()BKDWriter.merge()Lucene90PointsWriter.merge()
如果只看栈,很容易把问题归到 Easysearch 的 BKD merge 逻辑。但排查到最后,结论恰恰相反。
问题不在 Easysearch 的代码,而在 JDK 运行时。 更精确地说,是某个特定 Oracle GraalVM 21 构建中的 JVMCI/Graal JIT 路径,把 Lucene BKD 的热点代码执行错了。
1、为什么这个问题难查
它有几个特别迷惑人的特征:
- 只在高并发写入压测下触发
- 服务重启后的前几轮最容易复现
- 同一进程里,删了索引重新压,后面复现率反而下降
- 不是固定字段,多个数字类型字段都中过招
ZSTD和best_compression两种 codec 下都能复现
实际命中过的字段包括 @timestamp、size、status、_seq_no。所以这不是某个字段、某种 codec 或某个 mapping 的偶发问题。
2、第一层排除:merge reader 不是第一现场
一开始我们确实怀疑 merge reader,毕竟异常直接出现在 merge 路径上。但日志顺序很快给出了相反的证据。在 merge 真正崩溃之前,source segment 已经先出现了这些异常信号:
point-sort-restore-multiple-zero-ordssource-write-point-doc-mismatchpointCount > docCountpack-index-negative-codereader-invalid-start-pos- 最后才是
ArrayIndexOutOfBoundsException
这意味着两件事:merge reader 不是第一现场,source segment 在写出阶段就已经坏了。merge reader 只是读到了已经损坏的 BKD index,并在那个阶段暴露了异常。
3、第二层排除:Easysearch 自己的 BKD 写入逻辑也没有先出错
继续往前追溯,我们发现问题比 OneDimensionBKDWriter.add() 还要早。真正的异常出现在排序/回填链路上:
PointValuesWriterMutablePointTreeReaderUtils.sort()StableMSBRadixSorter
关键证据来自两个探针:
point-sort-restore-multiple-zero-ordsunwrittenSlotCount == source-write-point-doc-mismatch delta
这说明在某次排序/回填过程中,有一部分槽位根本没有被写入,默认值 0 被 restore 回填到 ords[],再通过 docIDs[0] 放大成大量 docID=0,最终导致 pointCount > docCount,source segment 进入错误状态。
到这一步,排查重点已经不是“Easysearch 的 BKD merge 逻辑存在缺陷”,而是 Lucene points 排序链路的执行结果和源码语义不一致。
4、真正的转折点:抓到了 reorder() 自身的 coverage 异常
真正把方向扭转过来的,不是又一次复现,而是一个更早的探针:
point-sort-reorder-coverage-mismatch
这个探针验证的是:StableMSBRadixSorter.reorder() 是否真的按源码应有的次数完整执行。
我们抓到的典型样本之一如下:
targetSegment=_xfield=statusk=7expectedLoopCount=9800actualIterationCount=8204firstCoverageMismatchBucket=201firstCoverageExpected=9788firstCoverageActual=8192
更关键的是,同一条日志里还带出了这个信息:
skippedSourceSamples=[201:[{ord=8192,bucket=201,docID=9090,byteAtK=200}, ...]]
这条信息非常重要,因为它说明:bucket 201 理论上应该处理 9788 条,实际只处理了前 8192 条,但从 ord=8192 往后的样本,读出来仍然还是 bucket=201。这直接推翻了“后半段数据被污染后改桶”的旧解释,指向了一个更直接的结论:reorder() 自己的 coverage 被截断了。
另一个样本中出现了同类边界:firstCoverageExpected=31822,firstCoverageActual=16384。
到这里,一个很不自然的特征浮现出来:8192、16384——这些明显的 2 的幂边界,更像是运行时或 JIT 执行异常,而不是普通业务逻辑 bug。
5、哪段代码最可疑
此时怀疑对象已经不是泛泛的“BKD 整体有问题”,而是 Lucene 中的这段热点循环:
for (int i = 0; i < HISTOGRAM_SIZE; ++i) {
final int limit = endOffsets[i];
for (int h1 = fixedStartOffsets[i]; h1 < limit; h1++) {
final int b = getBucket(from + h1, k);
final int h2 = startOffsets[b]++;
save(from + h1, from + h2);
}
}
restore(from, to);
代码位于 org.apache.lucene.util.StableMSBRadixSorter#reorder(...)。
按源码语义,这段代码应该完整扫描每个 bucket 的范围,并最终把全部结果 restore 回去。但我们抓到的事实是:expectedLoopCount != actualIterationCount,某些 bucket 只跑到 8192 / 16384 就停了,随后出现未写槽位,restore 把默认 0 回填,最终 source segment 进入错误状态。
如果这是 Java 源码本身的稳定逻辑 bug,它在解释执行时也应该稳定触发,而不应该强烈依赖某个 JDK/JIT 组合。后面的 JVM 对照实验基本排除了这个可能性。
6、最强证据:只换 JDK / JIT 路径,结果就变了
这次排查中最有说服力的,不是某一条日志,而是对照实验。
基线组:旧版 Oracle GraalVM 21,默认 JVMCI/Graal JIT
环境:
Oracle GraalVM 21+35.121+35-jvmci-23.1-b15Linux aarch64 / ARM64UseJVMCICompiler = true
结果:很快复现,命中了 point-sort-reorder-coverage-mismatch、point-sort-reorder-underfilled、point-sort-restore-multiple-zero-ords,随后 merge 报 ArrayIndexOutOfBoundsException: Index -4 out of bounds for length 8。
对照组:关闭 JVMCI/Graal JIT 或纯解释执行
只改 JVM 参数,不改代码和压测口径:
-XX:-UseJVMCICompiler-Xint
结果一致:都没有再出现上述探针和异常。
这三组对照的意义很直接:如果这是 Easysearch 或 Lucene 的纯 Java 逻辑 bug,解释执行也应该能稳定复现。但现实是基线组复现,关闭 JVMCI 和纯解释执行都不复现。问题显然高度依赖 JIT 路径。
版本对照:较新的 GraalVM 21 构建在当前测试中未复现
这里需要补充一条重要的边界条件。我们后来又测试了一个较新的 GraalVM 版本:
java version "21.0.9" 2025-10-21 LTS
Java(TM) SE Runtime Environment Oracle GraalVM 21.0.9+7.1 (build 21.0.9+7-LTS-jvmci-23.1-b79)
在当前压测中,这个版本没有再出现 merge 错误。
因此结论必须写得更精确:已知会复现的是较早的 21+35-jvmci-23.1-b15,已知在当前测试中未复现的是较新的 21.0.9+7-LTS-jvmci-23.1-b79。更准确的工程判断不是“GraalVM 21 整体都有问题”,而是某个特定 GraalVM 21 构建有问题,较新的构建很可能已经修复或规避了该问题。这里仍需保持严谨:只能说“在当前压测中未复现”,还不能直接说“已经被完整证明没有问题”。
平台边界:不能写成 ARM 专属
除了前面详细展开的 Linux aarch64 / ARM64 主要实验环境外,有用户反馈在以下环境中也出现过同类问题:
- 操作系统:
openEuler - 内核:
4.19.90-2112.8.0.0131.oe1.x86_64 - 架构:
x86_64
这是用户的测试环境,不是我们能够独立完整复现并逐项展开的。但这条信息已经足够说明:当前不能把问题简单写成“ARM 平台专属”。更准确的说法是:我们在 ARM64 上系统性复现并完成了主要对照实验,另外也有 openEuler x86_64 测试环境的同类现象反馈,因此平台边界目前还没有被完全钉死。
7、更强的同机对照:换成 Oracle HotSpot 21.0.10 后,全量写入跑完也没有问题
为了进一步排除“是不是所有 Java 21 都会这样”,我们在同一台服务器上把 /infini/easysearch/jdk 从 Oracle GraalVM 21 换成普通 Oracle HotSpot 21.0.10,恢复默认 JVM 参数,用同样的写入压测继续验证。
其中一轮的结果很有说服力:
- 索引:
nginx_zstd3_40mt4 - codec:
ZSTD threads=16bulk_size=1000target_docs=181463624
最终 after_count=181463624,delta_written=181463624,全量文档写入完成,服务端没有出现任何 BKD merge 错误。
这条结果至少说明:同一台机器、同一套 Easysearch、同样的数据规模和写入模型,只要把 JDK 从 Oracle GraalVM 21 换成 Oracle HotSpot 21.0.10,问题就不再出现。
到这一步,工程判断已经比较清晰了:不是 Easysearch 自身逻辑导致,也不是所有 Oracle JDK 21 都会出错,更像是特定 Oracle GraalVM 21 构建相关的 JVMCI/Graal JIT 路径问题。
8、最关键的外部对照:Elasticsearch 8.19.5 也复现了
如果说前面的结论还能被质疑为“Easysearch 某些实现差异触发的”,那么后面的外部对照基本排除了这个方向。
我们在同一台服务器上部署了 Elasticsearch 8.19.5(Lucene 9.12.2),JDK 也切到相同的 Oracle GraalVM 21,执行同类写入压测。结果 Elasticsearch 也复现了同样的 BKD merge 崩溃。
关键异常完全一致:
java.lang.ArrayIndexOutOfBoundsException: Index -4 out of bounds for length 8
栈也一样落在 BKDReader.readNodeData、BKDWriter$MergeReader.collectNextLeaf、BKDWriter$MergeReader.next。
这条证据的力度很强:不是 Easysearch 独有的问题,不是当前这套 Lucene 代码路径独有的问题,Elasticsearch 8.19.5 + Lucene 9.12.2 在同类 GraalVM 21 环境下也会出现同类异常。到这一步,再把问题归因于 Easysearch 本身的代码逻辑,已经缺乏依据了。
9、这次排查最终说明了什么
把整条证据链串起来,当前阶段的结论已经比较清楚。
已验证的事实:
- 问题不是 merge reader 先制造坏数据,source segment 在更早阶段就已经进入错误状态
- 不是单字段问题,也不是
ZSTD或best_compression专属 - 已抓到
StableMSBRadixSorter.reorder()自身的 coverage 异常 - 关闭
UseJVMCICompiler后问题不复现,-Xint下也不复现 - 同机切到
Oracle HotSpot 21.0.10后,Easysearch 全量写入跑完未见 BKD merge 异常 Elasticsearch 8.19.5 + Lucene 9.12.2在同类 GraalVM 21 环境下也复现- 较新的
21.0.9+7-LTS-jvmci-23.1-b79在当前压测中未复现 - 某用户的
openEuler x86_64测试环境中也出现过同类错误,因此不能写成 ARM 专属
工程结论:
从工程证据来看,Easysearch 本身的代码逻辑没有问题。
当前最符合事实的结论是:问题高度相关于特定 Oracle GraalVM 21 构建,更具体地,是该构建相关的 JVMCI/Graal JIT 路径。它把 Lucene BKD 相关热点代码执行到了错误状态。已知较早构建 21+35-jvmci-23.1-b15 可复现,已知较新的 21.0.9+7-LTS-jvmci-23.1-b79 在当前测试中未复现。平台边界目前尚未完全钉死,不能再简单写成仅限 ARM64。
换句话说,这不是“Easysearch 的 BKD merge 实现有 bug”,而是特定 JDK/JIT 运行时把本来正确的 Lucene BKD 代码执行错了。
10、建议版本与规避方案
如果你在生产或测试环境中运行 Easysearch 或 Elasticsearch,并且使用的是某些 Oracle GraalVM 21 构建,且启用了默认的 JVMCI/Graal JIT,那么在高并发写入、频繁 merge、BKD 热点路径被充分打热的场景下,需要特别警惕这类问题。
现阶段比较明确的建议是:
- 避免继续使用已经验证可复现的旧版构建:
Oracle GraalVM 21+35.1或21+35-jvmci-23.1-b15 - 优先升级到当前测试中未复现的版本:
Oracle GraalVM 21.0.9+7.1(即21.0.9+7-LTS-jvmci-23.1-b79) - 如果短期内不方便升级 GraalVM,直接切换到普通
Oracle HotSpot 21.0.10
直接落到版本号上会更清晰:
- 已确认应避开:
21+35-jvmci-23.1-b15 - 当前更推荐:
21.0.9+7-LTS-jvmci-23.1-b79
原因很简单:前者我们已经复现了,后者在当前压测中没有复现。当然,这里的“推荐”是基于当前测试结果,不代表上游已经正式确认该问题已被修复。
11、最后
这次排查最大的价值,不是“又复现了一次 BKD merge 崩溃”,而是把一个看起来像 Easysearch 代码 bug 的现象,收敛成了一个有明确边界的运行时问题。
它至少说明两件事:
- 栈顶报错的位置不一定是真正的第一现场
- 真正有说服力的不是猜测,而是对照实验
这次结论之所以成立,不是因为主观判断,而是因为我们已经拿到了足够强的工程证据:同机 HotSpot 不复现,关闭 JVMCI 不复现,解释执行不复现,Elasticsearch 也复现,较新的 GraalVM 21.0.9+7.1 在当前测试中未复现,且某用户的 openEuler x86_64 测试环境也出现过同类错误。
所以,这一次,问题确实不在 Easysearch,而在特定版本的 JDK/JIT 运行时。
关于 Easysearch

INFINI Easysearch 是一个分布式的搜索型数据库,实现非结构化数据检索、全文检索、向量检索、地理位置信息查询、组合索引查询、多语种支持、聚合分析等。Easysearch 可以完美替代 Elasticsearch,同时添加和完善多项企业级功能。Easysearch 助您拥有简洁、高效、易用的搜索体验。
官网文档:https://docs.infinilabs.com/easysearch
作者:张磊,极限科技(INFINI Labs)搜索引擎研发负责人,对 Elasticsearch 和 Lucene 源码比较熟悉,目前主要负责公司的 Easysearch 产品的研发以及客户服务工作。
相关文章:
【搜索客社区日报】第2214期 (2025-04-10)
社区日报 • Fred2000 发表了文章 • 0 个评论 • 11239 次浏览 • 2026-04-10 10:39
【 INFINI Workshop 北京站】1月18日一起动手实验玩转 Easysearch
活动 • liaosy 发表了文章 • 0 个评论 • 6902 次浏览 • 2023-12-15 16:22
与 INFINI Labs 的技术专家面对面,第一时间了解极限实验室的发布最新产品和功能特性,通过动手实战,快速掌握最前沿的搜索技术,并用于实际项目中。欢迎大家扫描海报二维码免费报名参加。
活动时间:2024-01-18 13:30~17:30
活动地点:北京市海淀区 Wework 辉煌时代大厦 3 楼 3E 会议室
分享议题
- Easysearch 总体介绍及搭建实战
- 基于 INFINI Console 实现跨版本、跨引擎统一管控
- Elasticsearch -> Easysearch 在线迁移实操
参会提示
- 请务必自备电脑(Windows 系统环境请提前安装好 Linux 虚拟机)
- 请提前在 INFINI Labs 官网下载对应平台最新安装包(INFINI Easysearch、INFINI Gateway、INFINI Console)
- 下载地址:https://www.infinilabs.com/download
- 如有任何疑问可添加 INFINI Labs 小助手(微信号: INFINI-Labs)进行联系
elasticsearcg索引配置不变,doc数量不变却越写越慢
回复Elasticsearch • kin122 回复了问题 • 2 人关注 • 3 个回复 • 20315 次浏览 • 2025-07-30 08:47
【字节跳动】 深圳/上海招聘Elasticsearch研发工程师
回复求职招聘 • tinycols 发起了问题 • 1 人关注 • 0 个回复 • 5328 次浏览 • 2024-12-05 16:57
3月26日 OpenSearch Community Meeting 视频回放
回复OpenSearch • Charele 回复了问题 • 2 人关注 • 1 个回复 • 7022 次浏览 • 2024-04-05 16:58
ElasticSearch自动补全,中文不准确的问题,请大家帮我看一下
回复Elasticsearch • God_lockin 回复了问题 • 2 人关注 • 1 个回复 • 5046 次浏览 • 2023-11-21 22:17
【搜索客社区日报】第2318期 (2026-11-02)
社区日报 • Muses 发表了文章 • 0 个评论 • 223 次浏览 • 14 小时前
【搜索客社区日报】第2318期 (2026-11-02)
社区日报 • Muses 发表了文章 • 0 个评论 • 224 次浏览 • 15 小时前
【搜索客社区日报】第2315期 (2026-10-26)
社区日报 • Muses 发表了文章 • 0 个评论 • 1974 次浏览 • 2026-10-26 14:12
【搜索客社区日报】第2313期 (2026-10-19)
社区日报 • Muses 发表了文章 • 0 个评论 • 3651 次浏览 • 2026-10-19 15:17
【搜索客社区日报】第2274期 (2026-07-27)
社区日报 • Muses 发表了文章 • 0 个评论 • 10310 次浏览 • 2026-09-17 18:59
【搜索客社区日报】第2298期 (2026-09-14)
社区日报 • Muses 发表了文章 • 0 个评论 • 7854 次浏览 • 2026-09-14 07:37
【搜索客社区日报】第2296期 (2026-09-07)
社区日报 • Muses 发表了文章 • 0 个评论 • 10898 次浏览 • 2026-09-07 14:40
从国产替代到自主创新:极限科技亮相 DTCC 2026,分享 Easysearch 信创实践
Easysearch • INFINI Labs 小助手 发表了文章 • 0 个评论 • 11468 次浏览 • 2026-08-26 16:27
8月20–22日,第17届中国数据库技术大会(DTCC 2026)在北京朗丽兹西山花园酒店举行。本届大会由 IT168 联合 ITPUB 主办,以“融数聚智 创领未来”为主题,汇聚众多数据库领域专家、技术从业者与企业代表,围绕数据库内核、云原生、AI、向量数据库、实时数仓、分布式数据库及行业实践等热点展开深入交流。
在8月21日下午的【向量数据库技术实践】专场,极限科技 CEO 曾勇带来主题分享《从国产替代到自主创新:Easysearch 在搜索引擎领域的信创实践》,从 AI 时代搜索引擎的新定位出发,系统分享搜索引擎国产化面临的关键挑战,以及 Easysearch 在兼容迁移、企业级能力、信创适配、安全容灾和 AI 搜索等方面的实践探索。

一、AI 时代,搜索引擎正在从“工具”走向“基础设施”
过去,搜索引擎主要承担“找到信息”的任务,以关键词匹配、倒排索引、全文检索和 BM25 等技术为核心,服务于企业文档搜索、网站搜索、日志检索和数据查询等场景。
而随着大模型、RAG 和 Agent 快速发展,搜索正在发生新的变化。
从“匹配字面”走向“理解语义”,从“返回结果”走向“辅助决策”,搜索引擎正在成为连接企业数据与 AI 能力的重要基础设施。

在曾勇的分享中,他将这一变化概括为:
从“找信息”走向“用知识”。
如今,企业知识库、智能客服、运维诊断助手、合规审查,以及多模态搜索、Agent 自主搜索等应用,都离不开高质量的检索能力。搜索引擎也因此成为 RAG 和 Agent 获取知识、理解上下文的重要底座。
这也意味着,搜索引擎一旦从普通工具升级为企业 AI 基础设施,其稳定性、安全性以及自主可控能力的重要性将进一步提升。
二、国产替代,不能只是“换一个引擎”
随着信创建设持续深入,国产化正在从基础设施和外围系统逐步进入核心业务与数据基础设施领域。
在曾勇看来,搜索引擎国产化并不是简单完成一次产品替换,而是一项涉及业务连续性、数据迁移、技术自主、安全合规和长期演进能力的系统工程。

因此,在进行搜索引擎国产化选型时,至少需要重点关注五个方面:
- 自主可控:核心引擎和关键技术是否真正掌握在自己手中;
- 企业级稳定性:能否支撑 TB/PB 级数据、高并发和 7×24 小时稳定运行;
- 信创真实适配:能否真正适配国产 CPU、操作系统等基础环境;
- 安全治理能力:权限、审计、加密、脱敏等能力是否能够内建;
- 长期演进能力:能否持续支撑向量检索、AI 搜索、多模态搜索等未来需求。
归根结底,企业选择的并不仅仅是一套搜索软件,而是未来数年持续承载企业数据和 AI 应用的技术底座。
三、从“敢替”到“好用”,Easysearch 持续构建企业级搜索底座
围绕企业国产化过程中最关心的“怎么替、怎么迁、怎么回退、谁来服务、如何运维”等问题,极限科技持续围绕 Easysearch 完善从搜索引擎内核到企业级平台的完整能力体系。
作为企业级分布式搜索型数据库,Easysearch 支持非结构化数据检索、全文检索、向量检索、地理位置查询、组合索引查询、多语种搜索和聚合分析,并提供企业级安全与管理能力。

1. 兼容生态,让迁移更平滑
对于已经大规模使用 Elasticsearch 的企业而言,迁移成本往往是国产替代过程中最现实的问题之一。
针对这一挑战,Easysearch 持续强化兼容能力,覆盖 REST API、Java/Python/Go/Node.js SDK、Query DSL,以及 ES 6.x/7.x/8.x 数据读写,并兼容 Kibana、Logstash、Beats、Filebeat 等常见生态工具。同时针对龙芯、鲲鹏、飞腾以及麒麟、统信 UOS 等国产软硬件环境开展适配。
这意味着企业在推进国产化时,可以尽可能复用现有应用、技术栈和运维经验,降低迁移改造成本。
2. 企业级能力,让国产搜索真正“好用”
国产化的终点并不是“能够运行”,而是能够真正支撑企业核心生产业务。
Easysearch 从内核层面持续补齐企业级能力,包括 TLS 加密、RBAC/ABAC 权限控制、字段级脱敏、LDAP/AD 认证、IP 黑白名单、防暴力破解、磁盘及快照加密、限流限速、审计日志、文档级权限以及国密算法等能力。
在安全与容灾方面,Easysearch 支持 SM2、SM3、SM4 国密算法,并提供全量/增量 Snapshot 备份、备份文件加密、跨集群复制以及跨机房部署等能力,为金融、政务等高安全、高可靠场景提供基础支撑。
四、从全文检索到向量检索,为 AI 应用打好搜索底座
AI 时代,搜索引擎需要解决的不再只是“关键词能不能搜到”,还需要理解数据背后的语义。
Easysearch 已将全文检索、向量检索与混合搜索能力统一在同一引擎中,支持 kNN 向量检索、HNSW/LSH 等向量索引方式,并支持 BM25 全文检索与向量相似度的双路召回和融合排序。

通过统一搜索引擎承载全文、向量和混合检索,可以减少企业额外部署独立向量数据库带来的架构复杂度与运维成本,并进一步支撑语义搜索、RAG、Agent 长期记忆、企业知识库和多模态检索等场景。
这也是 Easysearch 从传统搜索基础设施向 AI Search Infra 演进的重要一步。
五、立足自主研发,持续深耕搜索基础设施创新
本次 DTCC 2026 的技术分享,是极限科技对国产搜索信创实践的一次集中输出。未来,极限科技将继续坚持自主创新路线,以 Easysearch 为基础,进一步完善企业级搜索、向量检索、AI 搜索和自主可控能力,推动搜索基础设施从“国产替代”走向“自主创新”,为企业数智化与 AI 应用发展构建更加安全、稳定、开放、可持续的搜索技术底座。
Bboss v7.5.6 正式发布,全面兼容国产分布式搜索引擎 Easysearch
资讯动态 • INFINI Labs 小助手 发表了文章 • 0 个评论 • 13693 次浏览 • 2026-06-23 23:31
一、引言
2026 年 6 月 21 日,经过 Bboss 开源社区与极限科技(INFINI Labs)的紧密合作, Bboss v7.5.6 正式发布!
作为国内领先的 AI 智能体开发框架、数据采集同步 ETL 工具以及流批一体化计算引擎,Bboss 在本次更新中与国产分布式搜索引擎 Easysearch 完成深度兼容,其 Elasticsearch Java 客户端 全面兼容 Easysearch 1.x、2.x 全系列版本。开发者现在可以无缝使用 Bboss 客户端操作 Easysearch 集群,享受与 Elasticsearch 一致的开发体验。

二、Bboss Elasticsearch 客户端简介
Bboss 是一款高性能、高兼容性的搜索引擎 Java REST 客户端框架,基于 Apache License 2.0 开源,原生支持 Elasticsearch、Easysearch 和 Opensearch。
自带客户端集群节点负载均衡和容灾,多集群多数据源,自动索引托管,多种分页机制,傻瓜级 CRUD,脚本,SQL,JDBC,高亮,权重,聚合,IP,GEO 地理位置,父子嵌套,应有尽有。
核心特性
| 特性 | 说明 |
|---|---|
| 原生多引擎支持 | 完美支持 ES 1.x ~ 9.x、Easysearch 1.x ~ 2.x、Opensearch 1.x ~ 3.x |
| 学习成本低 | 无需学习额外 API,只需掌握 Elasticsearch DSL,极简使用方式 |
| 开箱即用 | Spring Boot 自动配置,无需复杂设置 |
| 高效异步处理 | 内置 BulkProcessor 异步批处理器,大幅提升写入性能 |
| 灵活查询方式 | 支持 DSL、SQL、O/R Mapping 多种查询模式 |
| 多数据源支持 | 一个应用可同时操作多个不同版本的搜索引擎集群 |
| 客户端负载均衡 | 默认启用客户端负载均衡,容灾性更好 |
| 完整的结果封装 | 返回结果支持 JSON、PO 对象、List 集合、Map 等多种类型 |
三、为什么选择 Bboss + Easysearch
将 Bboss 作为 Easysearch 的 Java 客户端,您将获得以下独特优势:
- 国产化技术栈:从底层搜索引擎到上层客户端框架,完全国产化自主可控,满足信创合规要求,无许可证风险。
- 极低迁移成本:如果您正在使用 Elasticsearch + Bboss 技术栈,切换到 Easysearch 几乎零成本,只需修改连接配置即可。
- 成熟稳定的客户端:Bboss 经过多年发展,已在国内众多企业和项目中得到广泛应用和验证,拥有活跃的中文社区和完善的文档支持。
- 丰富的生态能力:除了基础的 CRUD 操作,还提供数据采集 ETL、流批一体化计算、AI 智能体等丰富的扩展能力。
四、快速开始
通过以下简单步骤,即可在 Bboss 中接入 Easysearch:
1. 添加 Maven 依赖
<dependency>
<groupId>com.bbossgroups.plugins</groupId>
<artifactId>bboss-datatran-jdbc</artifactId>
<version>7.5.6</version>
</dependency>
2. 配置 Easysearch 连接
spring:
elasticsearch:
bboss:
elasticsearch:
rest:
hostNames: localhost:9200
useHttps: true # Easysearch 默认启用 HTTPS
elasticUser: admin
elasticPassword: your_password
3. 基础操作
@Service
public class DocumentService {
@Autowired
private BBossESStarter bbossESStarter;
// 插入文档
public void insertDocument() {
ClientInterface client = bbossESStarter.getRestClient();
Document doc = new Document();
doc.setId("1");
doc.setTitle("Easysearch 与 Bboss 集成");
doc.setContent("这是一篇关于集成的文章");
client.addDocument("documents", doc, "refresh=true");
}
// 查询文档
public Document getDocument(String id) {
ClientInterface client = bbossESStarter.getRestClient();
return client.getDocument("documents", id, Document.class);
}
// 按字段查询
public ESDatas<Document> searchByAuthor(String author) {
ClientInterface client = bbossESStarter.getRestClient();
return client.searchListByField(
"documents", "author.keyword", author,
Document.class, 0, 10
);
}
}
五、结语
Bboss v7.5.6 与 Easysearch 的深度兼容,是国产开源生态建设的又一重要成果。作为 Easysearch 原厂,我们欢迎更多像 Bboss 这样的优秀开源项目加入国产搜索引擎生态,共同推动国内搜索型数据库的发展与繁荣。
对于正在评估搜索引擎选型或计划进行国产替代的企业用户,Bboss + Easysearch 的组合无疑是值得信赖的选择。
立即体验 Easysearch,开启国产搜索引擎之旅:
- Easysearch 官网: https://easysearch.cn
- Bboss 官方文档: https://esdoc.bbossgroups.com
- Easysearch x Bboss 详细集成文档: https://docs.infinilabs.com/easysearch/main/docs/integrations/third-party/bboss
六、关于 Easysearch

INFINI Easysearch 是一个分布式的搜索型数据库,实现非结构化数据检索、全文检索、向量检索、地理位置信息查询、组合索引查询、多语种支持、聚合分析等。Easysearch 可以完美替代 Elasticsearch,同时添加和完善多项企业级功能。作为国内领先的国产搜索引擎产品,Easysearch 具备以下核心优势:
1. 国产化自主可控
自主研发,符合信创要求,无许可证风险,为企业提供安全可靠的技术保障。在当前国际形势日益复杂、信创需求持续提升的大背景下,Easysearch 为政府、金融、电信、能源等关键行业提供了值得信赖的搜索引擎基础设施。
2. 轻量级架构
相比传统搜索引擎,Easysearch 资源占用更少,启动更快速,显著降低企业运维成本。其精简的架构设计使得在同等硬件条件下可以承载更多的业务负载,特别适合资源受限的私有化部署场景。
3. 卓越性能表现
查询性能优异,能够满足大部分业务场景需求,用户体验流畅。通过持续的内核优化和算法改进,Easysearch 在多项基准测试中展现出媲美甚至超越同类产品的性能水平。
4. 良好兼容性
与 Elasticsearch 的 API 接口基本兼容,迁移成本较低,保护用户现有投资。这一特性使得基于 Elasticsearch 开发的应用可以快速平滑地迁移至 Easysearch,大大降低了国产替代的技术门槛。
社区福利
为感谢广大社区开发者的支持,Bboss 与 Easysearch 厂商极限科技联合发起抽奖活动,奖品为开源T恤。6 月 29 日上午 10 点自动开奖,欢迎大家扫码抽奖参与。
Elasticsearch 6/7/8 到 Easysearch 2.x 迁移指南
Easysearch • INFINI Labs 小助手 发表了文章 • 0 个评论 • 11731 次浏览 • 2026-06-04 14:14

最近在协助客户进行 Elasticsearch 到 Easysearch 的迁移时,发现大家最关心的问题是"当前版本能否直接使用快照迁移"。这个问题看似简单,但不同版本的答案差异较大。本文将基于实际测试经验,梳理各版本的迁移路径和注意事项。
迁移路径速览
根据源 ES 版本,可以直接对照下表选择迁移方案:
| 源 ES 版本 | 能否直接快照恢复 | 推荐方案 | 实施复杂度 |
|---|---|---|---|
| ES 6.x | 否 | INFINI Gateway 迁移 或 ES 7.10.x 中转 | 较低 |
| ES 7.0 - 7.11 | 是 | 直接快照恢复 | 较低 |
| ES 7.12 - 7.17 | 否 | INFINI Gateway 迁移 | 较低 |
| ES 8.x | 否 | INFINI Gateway 迁移 | 较低 |
结论:ES 7.0-7.11 是迁移最顺畅的版本窗口,可直接快照恢复;其他版本也有成熟的迁移方案,只是路径不同。
版本差异的原因
迁移路径的差异主要源于两方面:Lucene 版本兼容性和快照元数据格式变化。
Lucene 兼容性:Easysearch 2.x 底层要求的最低 Lucene 版本对应 ES 7.0.0。ES 6.x 的索引文件使用老版本 Lucene,直接恢复会报错:
The index was created with version [6.8.23] but the minimum compatible version is [7.0.0].
快照元数据格式:ES 7.12 开始在快照中引入 uuid、cluster_id 字段,7.14 增加 writer_uuid,8.x 又引入 transport_version。这些字段与 Easysearch 2.x 的快照解析器不兼容。
因此,ES 7.0-7.11 成为迁移的"黄金窗口"——既满足 Lucene 兼容性要求,快照格式又足够简洁。
ES 7.0-7.11:直接快照恢复
这是测试最充分的迁移路径,已验证版本包括 ES 7.0.1、7.8.1、7.10.2 OSS、7.11.2。
已验证能力:
- 单索引 / 多索引 / 通配符批量恢复
- 常见字段类型与别名
- 自定义 settings、多分片索引
- ILM 托管索引、数据流后备索引、冻结索引
操作步骤:
# 1. 源 ES 创建快照
PUT /_snapshot/my_backup/snapshot_1
{
"indices": "索引列表",
"include_global_state": false
}
# 2. Easysearch 注册同一快照仓库
PUT /_snapshot/my_backup
{
"type": "fs",
"settings": {
"location": "/path/to/snapshot/repo",
"readonly": true
}
}
# 3. 恢复快照
POST /_snapshot/my_backup/snapshot_1/_restore
{
"indices": "索引列表",
"include_global_state": false
}
ES 6.x:Gateway 迁移或中转方案
ES 6.x 无法直接快照恢复到 Easysearch 2.x,有两种迁移方案可选:
方案一:INFINI Gateway 迁移(推荐)
直接使用 Gateway 从 ES 6.x 迁移数据到 Easysearch,无需中转集群。Gateway 已验证支持 ES 6.8.x 的数据迁移。
方案二:ES 7.10.x 中转
ES 6.8 -> 快照 -> ES 7.10.x -> 快照 -> Easysearch 2.x
ES 7.10.x 可以正常恢复 ES 6.x 的快照,恢复完成后再创建快照供 Easysearch 使用。该方案数据完整性有保障,但需要额外的中转存储和迁移窗口。
ES 6.x 特有字段:ES 6.x 的 string 类型在 Easysearch 中需映射为 text 或 keyword(根据实际使用场景选择)。
ES 7.12+ 和 8.x:INFINI Gateway 迁移
这两个版本段的快照格式与 Easysearch 2.x 不兼容,推荐使用 INFINI Gateway 进行迁移。Gateway 是 INFINI Labs 提供的数据迁移工具,专门针对 Elasticsearch 到 Easysearch 的迁移场景进行了优化。
架构示意
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Elasticsearch │ ──── │ INFINI Gateway │ ──── │ Easysearch │
│ (源集群) │ │ (迁移工具) │ │ (目标集群) │
└─────────────────┘ └─────────────────┘ └─────────────────┘
Gateway 内部通过 Scroll API 从源集群分批拉取数据,再通过 Bulk API 写入目标集群,整个过程对业务透明。
主要优势
- 配置简单:只需配置源集群和目标集群地址、索引名称即可
- 断点续传:支持从断点恢复,避免网络抖动导致重头再来
- 进度可视:实时显示迁移进度和速率
- 多索引并行:支持同时迁移多个索引
基本步骤
- 在目标集群创建索引的 mapping 和 setting
- 准备 Gateway 配置文件,填写源集群和目标集群连接信息
- 运行 Gateway 执行迁移
- 迁移完成后进行数据校验
详细的配置说明和操作示例,可参考 ES 数据迁移之 INFINI Gateway。
备选方案
如果需要更灵活的控制,也可以自行编写脚本,通过 Scroll API 读取源数据、Bulk API 写入目标。这种方式适合有定制化需求的场景,但需要自行处理断点续传、错误重试等逻辑。
字段类型兼容性
直接兼容类型:text、keyword、long、double、boolean、date、object、nested、geo_point、geo_shape、ip、completion、wildcard、flattened、alias、join、rank_feature、rank_features、integer_range、long_range、date_range、match_only_text 等。
ES 7.x / 8.x 需替换类型:
| ES 类型 | Easysearch 替代方案 | 数据保留 | 说明 |
|---|---|---|---|
dense_vector |
knn_dense_float_vector |
是 | 需安装 knn 插件,向量数据格式兼容 |
knn_vector |
knn_dense_float_vector |
是 | 需安装 knn 插件 |
sparse_vector |
knn_sparse_bool_vector |
是 | 需安装 knn 插件 |
constant_keyword |
keyword |
是 | 需手动维护常量值 |
runtime |
移除或转为普通字段 | 是 | Easysearch 不支持运行时字段 |
histogram |
object |
是 | 聚合 histogram 功能丢失 |
aggregate_metric_double |
object |
是 | 需手动计算聚合 |
unsigned_long |
long 或 keyword |
是 | 注意数值范围 |
semantic |
暂不支持 | - | ES 专有 AI 功能 |
向量迁移要点:ES 的 dense_vector 数据可直接迁移到 Easysearch 的 knn_dense_float_vector,数据格式 [0.1, 0.2, ...] 完全兼容。需预先在目标索引创建正确的 mapping。
建议迁移前先用小索引测试,确认 mapping 无问题后再全量迁移。
常见问题与避坑指南
1. include_global_state 参数设置
该参数控制是否恢复集群级配置(模板、ILM 策略等)。不同版本的情况:
| ES 版本 | 发行版 | global_state | 说明 |
|---|---|---|---|
| 7.0-7.7 | 任意 | 兼容 | 无 _index_template API |
| 7.8-7.10 | OSS | 兼容 | 无内置 _index_template |
| 7.8-7.10 | default | 可能不兼容 | 取决于是否使用 _index_template |
| 7.11+ | 任意 | 不兼容 | 有 9 个内置 _index_template |
建议:迁移时统一使用 include_global_state=false,先恢复数据再重建配置。
2. ILM 和 data stream 迁移
- ILM:索引的 lifecycle 设置保留,但 policy 需在 Easysearch 中重建
- 数据流 (data stream):后备索引 (backing index) 数据完整恢复,语义需在目标侧重建
- 冻结索引 (frozen index):自动恢复为普通可访问状态
3. 迁移验收标准
建议至少完成三项验证:
- 文档量一致
- 关键查询结果一致
- 核心业务链路压测通过
4. 迁移窗口规划
- 快照方案通常需要短停机窗口完成切换
- Gateway 迁移可实现近实时同步,仅在切换连接时短暂停服
快照格式变化参考
| 字段 | ES 7.0-7.11 | ES 7.12-7.17 | ES 8.x | Easysearch 2.x |
|---|---|---|---|---|
min_version |
7.9.0 或无 | 7.12.0 | 7.12.0 | 支持 |
uuid(仓库级) |
无 | 有 | 有 | 不支持 |
cluster_id |
无 | 有 | 有 | 不支持 |
writer_uuid |
无 | 有(7.14+) | 有 | 不支持 |
transport_version |
无 | 无 | 有 | 不支持 |
总结
本文梳理了 Easysearch 2.x 对 ES 6/7/8 的迁移路径:
- ES 7.0-7.11:直接快照恢复,路径最短
- ES 6.x:INFINI Gateway 迁移 或 ES 7.10.x 中转
- ES 7.12+ / 8.x:使用 INFINI Gateway 迁移
建议在正式迁移前,先选择非核心索引进行小规模验证,确认数据完整性和业务兼容性后再扩大迁移范围。
如有迁移相关问题,欢迎联系我们。
【搜索客社区日报】第2237期 (2026-05-25)
社区日报 • Muses 发表了文章 • 0 个评论 • 10608 次浏览 • 2026-05-25 14:43
【搜索客社区日报】第2231期 (2026-05-15)
社区日报 • Fred2000 发表了文章 • 0 个评论 • 13687 次浏览 • 2026-05-15 10:19
Easysearch analysis-ik 多词典性能优化:从性能回退到分词性能提升 25%~30%
Easysearch • INFINI Labs 小助手 发表了文章 • 0 个评论 • 16446 次浏览 • 2026-05-08 14:34
Easysearch 版 analysis-ik 相比开源 IK 有一个重要的增强:支持多词典。简单说就是不同字段可以挂不同词库,可以叠加默认词典,也可以只用自定义词典。这是开源单词典 IK 做不到的。
功能实现初期,主要精力放在把能力跑通上。但在后来的一次写入压测中,我们发现 Easysearch 的写入吞吐和 Elasticsearch 有明显差距,最终定位到问题出在多词典的实现方式上——字段最终该用哪套词典,本来应该在分词前就算好,结果代码里把这个选择丢进了分词的热路径,每次分词都要反复切词典、重复扫同一段文本。
这篇文章记录的就是我们怎么一步步把性能拉回来、最终反超基线的过程。
问题怎么冒出来的
4 月 20 号,我们跑了一轮系统级写入压测。数据、mapping、settings、并发和 bulk 参数都一样,Elasticsearch 8.19.5 和 Easysearch 2.1.2 的写入吞吐差距大得有点不对劲:
| 时间 | 场景 | Elasticsearch | Easysearch | 说明 |
|---|---|---|---|---|
| 2026-04-20 第 2 次有效重跑 | 29900 docs / bulk=250 / concurrency=3 端到端写入压测 |
129.44 docs/s |
31.21 docs/s |
这是整条写入链路的 docs/s,不是单独分词吞吐 |
| 2026-04-20 诊断样本 | 5000 docs / bulk=250 / concurrency=3 |
156.25 docs/s |
30.67 docs/s |
Easysearch 的累计索引耗时约为 Elasticsearch 的 8.0x |
当时服务器上跑的就是早期多词典版本。后面修性能,追的就是这个版本和开源单词典 IK 基线之间的差距。
这一步还不能直接确定问题就在分词器。但差距摆在这儿了,得继续往下排。我们先排除了几个常见干扰因素:
refresh_interval- 动态同义词 HTTP 服务
- mapping / settings 不一致
- 网络层和 bulk 客户端本身
采样结果很快把范围收窄了。Elasticsearch 那边热点比较分散,Easysearch 这边呢,分词链路里出现了异常集中的开销——分词过程中反复做词典选择和字典查找。
瓶颈不在 Lucene 写入链路本身,就在 analysis-ik 的多词典实现上。
根因分析
第一类问题出在实现模型上。多词典想表达的是”这个字段最终用哪套词典”,这件事完全可以在分词前算好。但早期代码里,硬是把它变成了运行时的事:
- “字段用哪个词典”变成了”运行时多轮扫描”——同一段文本对着多套词典各来一遍。
- 全局字典切换的动作放进了每字符的热路径。
- 结果就是同一段文本的扫描和查找成本翻了好几倍。
所以问题不是多词典天然慢,是实现把本该提前算好的东西塞进了热路径反复做。
第二类问题是后续优化过程中留下的额外开销。后面加的跨边界、停用词、长文本等测试本身不是性能问题的来源,它们的作用是把正确性边界补齐,确保每次优化不会改变分词结果。
最后通过性能分析确认,残留开销主要来自两处:缓存命中前还在做不必要的数据复制;诊断逻辑在生产热路径上产生了额外开销。修完之后这两处热点都从火焰图上消失了,说明性能回退确实来自真实的代码路径成本,不是测试抖动。
修复过程
整个修复分四个阶段。
第一阶段:把多词典从”运行时分发”收敛为”最终有效词典视图”
多词典能力保留,但不再让分词器在热路径里反复切词典、重复扫文本。改成在分词前就把字段最终生效的词典算好,分词过程只面对一个已经收敛好的词典视图。
说白了就是把模型拉回正确方向——多词典管表达能力,热路径只管分词。
第二阶段:逐步打掉热路径上的常数开销
留下来的每一项优化,都经过正式性能测试和采样分析验证。原则就一条:不改分词语义,只减少热路径上反复发生的查找、分配和判断。
第三阶段:补齐正确性护栏
正确性测试必须先到位,不然吞吐提升没有意义——万一分词结果变了,跑得再快也白搭。
这一轮重点覆盖了这些容易出问题的场景:
- 真跨边界场景
- 数字和量词合并,如
1号 - 自定义词典里的含符号词
- 补充平面字符跨边界稳定性
- 停用词过滤后的偏移量
- 长文本样本的稳定性
- 正式性能测试数据集的分词结果对齐
后面所有的吞吐数字,前提都是分词结果一致,避免把分词行为的变化误当成性能提升。
第四阶段:清理最后的残留开销
到 4 月 28 号,最后一轮修复集中处理两个地方:
- 词典视图命中缓存时直接返回,不再多做一次数据复制
- 诊断逻辑默认关掉,不让线上请求为调试能力买单
这两处修完,Easysearch 版 IK 就不只是恢复到单词典版本附近了,在正式测试里已经明显领先。
用数据看恢复过程
为了不把系统级写入压测和分词器性能测试混在一起,下面只看几个关键节点。2026-04-20 的 docs/s 是系统级写入吞吐,后面的 tok/s 是单独的分词器吞吐。
这里说的”开源 IK 基线”就是开源 IK 的单词典实现对照版本。所有正式吞吐结论都建立在同一数据集、同一测试方法、分词结果一致的前提上。
| 时间 | 口径 | 关键结果 | 说明 |
|---|---|---|---|
| 2026-04-23 17:02 CST | 初期本地复现 | 服务器多词典版本 61.39 万 tok/s,单词典版本 114.48 万 tok/s |
单词典版本快 86.49%,性能差距被明确复现 |
| 2026-04-24 09:51:12~09:55:15 CST | 第一次正式追平 | smart 相对开源单词典基线 +7.26% |
从明显落后追到略微领先 |
| 2026-04-25 04:14~04:16 CST | 双模式阶段复核 | smart +16.88%,max_word +20.09% |
领先优势开始扩大 |
| 2026-04-28 12:30:56 CST | 最新正式复核 | smart +30.96%,max_word +21.31% |
当前最新结果 |
整个过程就是:
- 先暴露出明显的性能退化
- 逐步缩小差距
- 追平,然后开始领先
- 最终在分词结果完全一致的前提下,正式反超
最早的本地复现数据很关键:服务器当时跑的多词典版本只有 613896.67 tok/s,单词典版本 1144843.77 tok/s。后面所有修复就是冲着这个差距去的。
三张图分别对应问题暴露、分词复现和修复结果:第一张展示服务器 bulk 写入吞吐的系统级差距;第二张展示多词典版本和单词典版本的本地分词差距;第三张展示分词结果对齐后,Easysearch 版 IK 怎么一步步追上来,最终实现 25%~30% 的分词性能提升。
为什么说 Easysearch 版 IK 现在更好
这次修复的价值不只是消灭了几个热点,更重要的是把多词典能力、分词正确性和性能测试体系一起补齐了。
1. 功能更强,性能代价可控
开源单词典 IK 模型简单,但表达能力也弱。Easysearch 的多词典能力要解决的是字段级词库隔离、自定义词典叠加这些实际需求。
关键问题是:能不能把这些能力的性能开销压到足够低。修复后的结果证明,可以。
2. 正确性护栏更完整
这轮补上的测试不只是几个短样例,覆盖了更容易翻车的边界条件:
- 真跨边界场景
- 长文本稳定性
- 自定义词典和符号词
- 数字量词合并
- 停用词过滤后的偏移量
这意味着以后再做性能优化,必须同时保证分词结果不变。想靠改分词行为换吞吐,测试会先拦住。
3. 性能测试体系更严格
这轮之后,Easysearch 对 analysis-ik 的正式性能结论统一按一套标准出:
- 同一数据集
- 同一测试方法
smart和max_word双模式- 分词结果一致
- 有性能分析结果支撑
这套体系能避免两个常见坑:只看单轮吞吐波动就下结论,或者分词结果已经变了还在比性能。
小结
多词典能力在实现初期,主要精力放在功能补齐上——先把字段级词库隔离、自定义词典叠加这些能力跑通,性能优化是后面分阶段来的事,没办法一蹴而就。
这轮优化下来,核心思路其实就一条:把词典选择从分词热路径里挪出去,提前收敛好,让分词过程只面对最终的词典视图。再配合热点清理和正确性护栏,增强功能和更高性能完全可以兼得。
截至 2026 年 4 月 28 日,在本地 Mac 笔记本上的多轮 benchmark 中,Easysearch 版 IK 在 smart 模式大约领先开源单词典 IK 基线 25%~30%,max_word 模式大约领先 20% 左右,分词结果完全一致。具体数字每次跑会有波动,但趋势是稳定的。
这也是 Easysearch 版 IK 相对开源版更有价值的地方:不是多了几个配置项,而是在多词典能力、分词正确性和分词性能三个方面都给出了可验证的结果。
关于 Easysearch

INFINI Easysearch 是一个分布式的搜索型数据库,实现非结构化数据检索、全文检索、向量检索、地理位置信息查询、组合索引查询、多语种支持、聚合分析等。Easysearch 可以完美替代 Elasticsearch,同时添加和完善多项企业级功能。Easysearch 助您拥有简洁、高效、易用的搜索体验。
作者:张磊,极限科技(INFINI Labs)搜索引擎研发负责人,对 Elasticsearch 和 Lucene 源码比较熟悉,目前主要负责公司的 Easysearch 产品的研发以及客户服务工作。
相关文章:
Easysearch BKD Merge 异常排查实录:最终定位到旧版 GraalVM JIT 运行时
Easysearch • INFINI Labs 小助手 发表了文章 • 0 个评论 • 12087 次浏览 • 2026-04-10 17:51
最近一次高并发写入压测中,我们遇到了一个非常诡异的 BKD merge 崩溃。从报错看,很像 Easysearch 2.1.2 在 merge 阶段把 segment 读成了错误状态。典型错误是这样的:
java.lang.ArrayIndexOutOfBoundsException: Index -3 out of bounds for length 8
java.lang.ArrayIndexOutOfBoundsException: Index -4 out of bounds for length 8
异常栈最终落在 Lucene BKD 相关路径上:
BKDReader.readNodeData()BKDWriter.merge()Lucene90PointsWriter.merge()
如果只看栈,很容易把问题归到 Easysearch 的 BKD merge 逻辑。但排查到最后,结论恰恰相反。
问题不在 Easysearch 的代码,而在 JDK 运行时。 更精确地说,是某个特定 Oracle GraalVM 21 构建中的 JVMCI/Graal JIT 路径,把 Lucene BKD 的热点代码执行错了。
1、为什么这个问题难查
它有几个特别迷惑人的特征:
- 只在高并发写入压测下触发
- 服务重启后的前几轮最容易复现
- 同一进程里,删了索引重新压,后面复现率反而下降
- 不是固定字段,多个数字类型字段都中过招
ZSTD和best_compression两种 codec 下都能复现
实际命中过的字段包括 @timestamp、size、status、_seq_no。所以这不是某个字段、某种 codec 或某个 mapping 的偶发问题。
2、第一层排除:merge reader 不是第一现场
一开始我们确实怀疑 merge reader,毕竟异常直接出现在 merge 路径上。但日志顺序很快给出了相反的证据。在 merge 真正崩溃之前,source segment 已经先出现了这些异常信号:
point-sort-restore-multiple-zero-ordssource-write-point-doc-mismatchpointCount > docCountpack-index-negative-codereader-invalid-start-pos- 最后才是
ArrayIndexOutOfBoundsException
这意味着两件事:merge reader 不是第一现场,source segment 在写出阶段就已经坏了。merge reader 只是读到了已经损坏的 BKD index,并在那个阶段暴露了异常。
3、第二层排除:Easysearch 自己的 BKD 写入逻辑也没有先出错
继续往前追溯,我们发现问题比 OneDimensionBKDWriter.add() 还要早。真正的异常出现在排序/回填链路上:
PointValuesWriterMutablePointTreeReaderUtils.sort()StableMSBRadixSorter
关键证据来自两个探针:
point-sort-restore-multiple-zero-ordsunwrittenSlotCount == source-write-point-doc-mismatch delta
这说明在某次排序/回填过程中,有一部分槽位根本没有被写入,默认值 0 被 restore 回填到 ords[],再通过 docIDs[0] 放大成大量 docID=0,最终导致 pointCount > docCount,source segment 进入错误状态。
到这一步,排查重点已经不是“Easysearch 的 BKD merge 逻辑存在缺陷”,而是 Lucene points 排序链路的执行结果和源码语义不一致。
4、真正的转折点:抓到了 reorder() 自身的 coverage 异常
真正把方向扭转过来的,不是又一次复现,而是一个更早的探针:
point-sort-reorder-coverage-mismatch
这个探针验证的是:StableMSBRadixSorter.reorder() 是否真的按源码应有的次数完整执行。
我们抓到的典型样本之一如下:
targetSegment=_xfield=statusk=7expectedLoopCount=9800actualIterationCount=8204firstCoverageMismatchBucket=201firstCoverageExpected=9788firstCoverageActual=8192
更关键的是,同一条日志里还带出了这个信息:
skippedSourceSamples=[201:[{ord=8192,bucket=201,docID=9090,byteAtK=200}, ...]]
这条信息非常重要,因为它说明:bucket 201 理论上应该处理 9788 条,实际只处理了前 8192 条,但从 ord=8192 往后的样本,读出来仍然还是 bucket=201。这直接推翻了“后半段数据被污染后改桶”的旧解释,指向了一个更直接的结论:reorder() 自己的 coverage 被截断了。
另一个样本中出现了同类边界:firstCoverageExpected=31822,firstCoverageActual=16384。
到这里,一个很不自然的特征浮现出来:8192、16384——这些明显的 2 的幂边界,更像是运行时或 JIT 执行异常,而不是普通业务逻辑 bug。
5、哪段代码最可疑
此时怀疑对象已经不是泛泛的“BKD 整体有问题”,而是 Lucene 中的这段热点循环:
for (int i = 0; i < HISTOGRAM_SIZE; ++i) {
final int limit = endOffsets[i];
for (int h1 = fixedStartOffsets[i]; h1 < limit; h1++) {
final int b = getBucket(from + h1, k);
final int h2 = startOffsets[b]++;
save(from + h1, from + h2);
}
}
restore(from, to);
代码位于 org.apache.lucene.util.StableMSBRadixSorter#reorder(...)。
按源码语义,这段代码应该完整扫描每个 bucket 的范围,并最终把全部结果 restore 回去。但我们抓到的事实是:expectedLoopCount != actualIterationCount,某些 bucket 只跑到 8192 / 16384 就停了,随后出现未写槽位,restore 把默认 0 回填,最终 source segment 进入错误状态。
如果这是 Java 源码本身的稳定逻辑 bug,它在解释执行时也应该稳定触发,而不应该强烈依赖某个 JDK/JIT 组合。后面的 JVM 对照实验基本排除了这个可能性。
6、最强证据:只换 JDK / JIT 路径,结果就变了
这次排查中最有说服力的,不是某一条日志,而是对照实验。
基线组:旧版 Oracle GraalVM 21,默认 JVMCI/Graal JIT
环境:
Oracle GraalVM 21+35.121+35-jvmci-23.1-b15Linux aarch64 / ARM64UseJVMCICompiler = true
结果:很快复现,命中了 point-sort-reorder-coverage-mismatch、point-sort-reorder-underfilled、point-sort-restore-multiple-zero-ords,随后 merge 报 ArrayIndexOutOfBoundsException: Index -4 out of bounds for length 8。
对照组:关闭 JVMCI/Graal JIT 或纯解释执行
只改 JVM 参数,不改代码和压测口径:
-XX:-UseJVMCICompiler-Xint
结果一致:都没有再出现上述探针和异常。
这三组对照的意义很直接:如果这是 Easysearch 或 Lucene 的纯 Java 逻辑 bug,解释执行也应该能稳定复现。但现实是基线组复现,关闭 JVMCI 和纯解释执行都不复现。问题显然高度依赖 JIT 路径。
版本对照:较新的 GraalVM 21 构建在当前测试中未复现
这里需要补充一条重要的边界条件。我们后来又测试了一个较新的 GraalVM 版本:
java version "21.0.9" 2025-10-21 LTS
Java(TM) SE Runtime Environment Oracle GraalVM 21.0.9+7.1 (build 21.0.9+7-LTS-jvmci-23.1-b79)
在当前压测中,这个版本没有再出现 merge 错误。
因此结论必须写得更精确:已知会复现的是较早的 21+35-jvmci-23.1-b15,已知在当前测试中未复现的是较新的 21.0.9+7-LTS-jvmci-23.1-b79。更准确的工程判断不是“GraalVM 21 整体都有问题”,而是某个特定 GraalVM 21 构建有问题,较新的构建很可能已经修复或规避了该问题。这里仍需保持严谨:只能说“在当前压测中未复现”,还不能直接说“已经被完整证明没有问题”。
平台边界:不能写成 ARM 专属
除了前面详细展开的 Linux aarch64 / ARM64 主要实验环境外,有用户反馈在以下环境中也出现过同类问题:
- 操作系统:
openEuler - 内核:
4.19.90-2112.8.0.0131.oe1.x86_64 - 架构:
x86_64
这是用户的测试环境,不是我们能够独立完整复现并逐项展开的。但这条信息已经足够说明:当前不能把问题简单写成“ARM 平台专属”。更准确的说法是:我们在 ARM64 上系统性复现并完成了主要对照实验,另外也有 openEuler x86_64 测试环境的同类现象反馈,因此平台边界目前还没有被完全钉死。
7、更强的同机对照:换成 Oracle HotSpot 21.0.10 后,全量写入跑完也没有问题
为了进一步排除“是不是所有 Java 21 都会这样”,我们在同一台服务器上把 /infini/easysearch/jdk 从 Oracle GraalVM 21 换成普通 Oracle HotSpot 21.0.10,恢复默认 JVM 参数,用同样的写入压测继续验证。
其中一轮的结果很有说服力:
- 索引:
nginx_zstd3_40mt4 - codec:
ZSTD threads=16bulk_size=1000target_docs=181463624
最终 after_count=181463624,delta_written=181463624,全量文档写入完成,服务端没有出现任何 BKD merge 错误。
这条结果至少说明:同一台机器、同一套 Easysearch、同样的数据规模和写入模型,只要把 JDK 从 Oracle GraalVM 21 换成 Oracle HotSpot 21.0.10,问题就不再出现。
到这一步,工程判断已经比较清晰了:不是 Easysearch 自身逻辑导致,也不是所有 Oracle JDK 21 都会出错,更像是特定 Oracle GraalVM 21 构建相关的 JVMCI/Graal JIT 路径问题。
8、最关键的外部对照:Elasticsearch 8.19.5 也复现了
如果说前面的结论还能被质疑为“Easysearch 某些实现差异触发的”,那么后面的外部对照基本排除了这个方向。
我们在同一台服务器上部署了 Elasticsearch 8.19.5(Lucene 9.12.2),JDK 也切到相同的 Oracle GraalVM 21,执行同类写入压测。结果 Elasticsearch 也复现了同样的 BKD merge 崩溃。
关键异常完全一致:
java.lang.ArrayIndexOutOfBoundsException: Index -4 out of bounds for length 8
栈也一样落在 BKDReader.readNodeData、BKDWriter$MergeReader.collectNextLeaf、BKDWriter$MergeReader.next。
这条证据的力度很强:不是 Easysearch 独有的问题,不是当前这套 Lucene 代码路径独有的问题,Elasticsearch 8.19.5 + Lucene 9.12.2 在同类 GraalVM 21 环境下也会出现同类异常。到这一步,再把问题归因于 Easysearch 本身的代码逻辑,已经缺乏依据了。
9、这次排查最终说明了什么
把整条证据链串起来,当前阶段的结论已经比较清楚。
已验证的事实:
- 问题不是 merge reader 先制造坏数据,source segment 在更早阶段就已经进入错误状态
- 不是单字段问题,也不是
ZSTD或best_compression专属 - 已抓到
StableMSBRadixSorter.reorder()自身的 coverage 异常 - 关闭
UseJVMCICompiler后问题不复现,-Xint下也不复现 - 同机切到
Oracle HotSpot 21.0.10后,Easysearch 全量写入跑完未见 BKD merge 异常 Elasticsearch 8.19.5 + Lucene 9.12.2在同类 GraalVM 21 环境下也复现- 较新的
21.0.9+7-LTS-jvmci-23.1-b79在当前压测中未复现 - 某用户的
openEuler x86_64测试环境中也出现过同类错误,因此不能写成 ARM 专属
工程结论:
从工程证据来看,Easysearch 本身的代码逻辑没有问题。
当前最符合事实的结论是:问题高度相关于特定 Oracle GraalVM 21 构建,更具体地,是该构建相关的 JVMCI/Graal JIT 路径。它把 Lucene BKD 相关热点代码执行到了错误状态。已知较早构建 21+35-jvmci-23.1-b15 可复现,已知较新的 21.0.9+7-LTS-jvmci-23.1-b79 在当前测试中未复现。平台边界目前尚未完全钉死,不能再简单写成仅限 ARM64。
换句话说,这不是“Easysearch 的 BKD merge 实现有 bug”,而是特定 JDK/JIT 运行时把本来正确的 Lucene BKD 代码执行错了。
10、建议版本与规避方案
如果你在生产或测试环境中运行 Easysearch 或 Elasticsearch,并且使用的是某些 Oracle GraalVM 21 构建,且启用了默认的 JVMCI/Graal JIT,那么在高并发写入、频繁 merge、BKD 热点路径被充分打热的场景下,需要特别警惕这类问题。
现阶段比较明确的建议是:
- 避免继续使用已经验证可复现的旧版构建:
Oracle GraalVM 21+35.1或21+35-jvmci-23.1-b15 - 优先升级到当前测试中未复现的版本:
Oracle GraalVM 21.0.9+7.1(即21.0.9+7-LTS-jvmci-23.1-b79) - 如果短期内不方便升级 GraalVM,直接切换到普通
Oracle HotSpot 21.0.10
直接落到版本号上会更清晰:
- 已确认应避开:
21+35-jvmci-23.1-b15 - 当前更推荐:
21.0.9+7-LTS-jvmci-23.1-b79
原因很简单:前者我们已经复现了,后者在当前压测中没有复现。当然,这里的“推荐”是基于当前测试结果,不代表上游已经正式确认该问题已被修复。
11、最后
这次排查最大的价值,不是“又复现了一次 BKD merge 崩溃”,而是把一个看起来像 Easysearch 代码 bug 的现象,收敛成了一个有明确边界的运行时问题。
它至少说明两件事:
- 栈顶报错的位置不一定是真正的第一现场
- 真正有说服力的不是猜测,而是对照实验
这次结论之所以成立,不是因为主观判断,而是因为我们已经拿到了足够强的工程证据:同机 HotSpot 不复现,关闭 JVMCI 不复现,解释执行不复现,Elasticsearch 也复现,较新的 GraalVM 21.0.9+7.1 在当前测试中未复现,且某用户的 openEuler x86_64 测试环境也出现过同类错误。
所以,这一次,问题确实不在 Easysearch,而在特定版本的 JDK/JIT 运行时。
关于 Easysearch

INFINI Easysearch 是一个分布式的搜索型数据库,实现非结构化数据检索、全文检索、向量检索、地理位置信息查询、组合索引查询、多语种支持、聚合分析等。Easysearch 可以完美替代 Elasticsearch,同时添加和完善多项企业级功能。Easysearch 助您拥有简洁、高效、易用的搜索体验。
官网文档:https://docs.infinilabs.com/easysearch
作者:张磊,极限科技(INFINI Labs)搜索引擎研发负责人,对 Elasticsearch 和 Lucene 源码比较熟悉,目前主要负责公司的 Easysearch 产品的研发以及客户服务工作。
相关文章:
【搜索客社区日报】第2214期 (2025-04-10)
社区日报 • Fred2000 发表了文章 • 0 个评论 • 11239 次浏览 • 2026-04-10 10:39

