ZincSearch — 单二进制 Go 写的 ES 替代
待复核ZincSearch 是 Prabhat Sharma(前 AWS Solutions Architect)2021 年用 Go 写的轻量级搜索引擎,目标只有一个:把 elasticsearch 那 1-2GB JVM heap 压成几十到一百多 MB 的常驻内存。
日常类比:
- elasticsearch 像一栋装满消防、空调、配电的大楼——功能齐,启动慢,水电费贵
- ZincSearch 像一台路边咖啡车——功能少一截,但插电就能营业,整车还没大楼一间办公室大
ZincSearch 不重写搜索本身。底层用 Bluge(纯 Go 索引库,和 tantivy、Bleve 同代),上面套 ES 兼容 REST API + Vue Web UI,打成一个静态二进制。docker 一行起服务,curl 直接灌数据。
不理解 ZincSearch 的取舍,下面这些事会困惑:
- ES 太重在很多场景是真问题:边缘节点 / 树莓派 / 小 VPS / 个人项目,上 ES 等于整台机器只剩它一个进程。ZincSearch 把搜索门槛拉回约 100 MB 级。
- 单二进制 = 运维成本骤降:不用 JVM、不用配
vm.max_map_count、不用调 heap。新人 docker pull 后几分钟就有可用搜索。 - ES API 兼容意味着迁移成本低:已有
_bulk/_doc灌数代码可改 host 直跑,不用重写客户端。 - 作者已转向另一条产品线:2022-2023 同一作者开了 OpenObserve 做日志可观测性。ZincSearch 现偏「搜索专用」,日志场景官方指向 OpenObserve。
ZincSearch 凭什么轻?拆三件事:
1. 用 Bluge 而不是 Lucene
Section titled “1. 用 Bluge 而不是 Lucene”elasticsearch 底层是 Lucene(Java,跑在 JVM 上)。ZincSearch 底层是 Bluge——Marty Schoch 等人用 Go 重写的纯 Go 索引库,是 Bleve 的演进版。类比:同一本电话簿,换了一套更轻的装订机。它共用 Vellum(FST 库;FST 像「按字母快速翻页的目录树」)。
直接收益:没有 JVM 几百 MB heap 起步价;静态二进制不用装运行时;Goroutine 并发开销通常低于 JVM 线程。
2. 单机,不做集群
Section titled “2. 单机,不做集群”ES 复杂度一半来自分布式(分片、副本、coordinator)。ZincSearch 砍掉这一层——只跑单机,不做 HA。这是它能做小的根本原因。代价:单机性能就是天花板;对「中小数据量 + 应用内搜索」通常够用。
3. 兼容 ES API 而不是重新发明
Section titled “3. 兼容 ES API 而不是重新发明”REST 照搬 _bulk、_doc、_search 路径。DSL 查询语法部分兼容(官方仍标 work-in-progress)。类比:插座形状一样,但里面接线只接了常用那几根——简单电器能插,复杂电器可能不通。迁移成本接近零,是拿用户的关键钩子。
案例 1:docker 一行起服务
Section titled “案例 1:docker 一行起服务”docker run -p 4080:4080 \ -e ZINC_FIRST_ADMIN_USER=admin \ -e ZINC_FIRST_ADMIN_PASSWORD=Pass123 \ public.ecr.aws/zinclabs/zincsearch:latest逐部分解释:-p 4080:4080 把容器 4080 映到本机;两个 -e 设首个管理员;镜像建议生产钉具体版本,勿长期依赖 latest。跑完打开 localhost:4080 进 Vue UI。对比 ES 首次常要改 vm.max_map_count、设密码、调 heap。
案例 2:灌一批文档(ES 兼容 _bulk)
Section titled “案例 2:灌一批文档(ES 兼容 _bulk)”curl -X POST 'http://localhost:4080/api/_bulk' \ -u admin:Pass123 \ -H 'Content-Type: application/json' \ --data-binary $'{"index":{"_index":"movies"}}\n{"title":"Matrix","year":1999}\n{"index":{"_index":"movies"}}\n{"title":"Inception","year":2010}\n'逐部分解释:-u 是 Basic 认证;body 是 NDJSON——奇数行写动作(写进哪个 index),偶数行写文档。不用先 PUT mapping;schema-less,字段类型自动推断。
案例 3:搜索(注意是 native API)
Section titled “案例 3:搜索(注意是 native API)”curl -X POST 'http://localhost:4080/api/movies/_search' \ -u admin:Pass123 \ -H 'Content-Type: application/json' \ --data '{"search_type":"match","query":{"term":"matrix","field":"title"}}'逐部分解释:路径仍像 ES,但 body 是 ZincSearch native schema(search_type + query.term/field),不是完整 ES Query DSL。复杂 DSL 可能失败——生产前用真实 query 测兼容层。
案例 4:内存占用对比(量级示意)
Section titled “案例 4:内存占用对比(量级示意)”同样灌约 100 万条 1KB 文档时的量级示意(非可复现 benchmark):
| 引擎 | 常驻 RSS | 启动时间 |
|---|---|---|
| elasticsearch 8.x | 约 1.5-2 GB(默认 heap) | 约 30-60 秒 |
| ZincSearch v0.4 | 约 80-150 MB | < 2 秒 |
桥接:RSS 是进程实际占的内存;ES 的 heap 是 JVM 预留的大块。差一个数量级,是个人项目 / 边缘节点选 ZincSearch 的核心理由。
- DSL 兼容是 work-in-progress:复杂查询(nested、has_child、function_score、pipeline aggregation)大概率不工作。生产前用真实 query 跑一遍兼容性测试,别假设 ES 客户端原样能用。
- 没有集群 = 没有水平扩展:单机塞满就只能升配 / 拆 index / 上下游手动分流。数据涨到几百 GB 就该重新评估,回 elasticsearch / opensearch / meilisearch 集群版本。
- 作者重心已转 OpenObserve:v0.4.10(2024 年 1 月)后维护节奏变慢,issue 响应慢于早期。日志场景官方明说让你去用 OpenObserve,搜索场景靠社区维护。
- 磁盘存储无对象后端:默认本地磁盘,无内置 S3 / MinIO。要冷热分层、跨机共享需要自己在外面搭。OpenObserve 有 S3 后端,ZincSearch 没有。
- 聚合能力比 ES 弱一截:基础 terms / metric agg 可用;nested、pipeline、bucket script 这些 ES 高级聚合大概率不行。复杂 BI 场景别指望它。
适用 vs 不适用场景
Section titled “适用 vs 不适用场景”适用:
- 应用内搜索 / 文档站搜索 / 博客搜索
- 资源受限节点(边缘、树莓派、低配 VPS、Serverless 容器)
- 中小数据量(< 100 GB)单机搜索
- 已有 ES
_bulk客户端代码,想低成本换底层
不适用:
- 大规模日志检索 → elasticsearch / opensearch / OpenObserve
- 需要分布式 HA / 跨机分片 → elasticsearch
- 重度复杂聚合 / nested DSL → elasticsearch
- C 端搜索追求拼写容错出色 → meilisearch
- 嵌入式搜索库(不要服务进程)→ tantivy / minisearch
历史小故事(可跳过)
Section titled “历史小故事(可跳过)”- 2021:Prabhat Sharma 在
prabhatsharma/zinc起项目,受不了业务搜索上 JVM 内存 - 2022:改名 ZincSearch,组织迁到
zincsearch/zincsearch - 2022-2023:开 ZincObserve(后更名 OpenObserve),把日志/指标/追踪从 ZincSearch 拆出
- 2024-01:v0.4.10(pre-GA);重心转 OpenObserve 后社区接手
轨迹典型:先做资源敏感的「小 ES」→ 发现日志与搜索是两件事 → 拆产品。meilisearch 偏开发者体验,ZincSearch 偏资源占用。
- 重写可以做得更小——砍掉分布式层、换语言换索引库,目标是把内存压到约 1/10
- API 兼容是迁移最强钩子——复用
_bulk/_doc,迁移成本接近零 - Java → Go 常换来静态二进制 + 无 JVM 暖机/heap 起步价 + 资源骤降——caddy、meilisearch(Rust)也走过类似路
- 作者注意力是隐性资源——慢下来往往是精力投到 OpenObserve,不只是技术债
- 官方文档
- elasticsearch —— 工业标准对照,理解砍掉了什么
- meilisearch —— 同代另一种「反 ES」路线(Rust + 开发者体验)
- tantivy —— Rust 版 Lucene,Bluge 在 Go 生态的对手
- opensearch —— ES 的 AWS fork,仍偏重
- elasticsearch —— 直接对标,理解砍了哪些功能
- meilisearch —— 同样轻量化,但侧重开发者体验
- opensearch —— 仍重,与 ZincSearch 价值取向相反
- tantivy —— Rust 版 Lucene;Bluge 是 Go 生态同位
- minisearch —— 浏览器内嵌入式搜索,比 ZincSearch 更小
(暂无反向链接)