跳转到内容

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 的取舍,下面这些事会困惑:

  1. ES 太重在很多场景是真问题:边缘节点 / 树莓派 / 小 VPS / 个人项目,上 ES 等于整台机器只剩它一个进程能跑。ZincSearch 的卖点就是把 “搜索” 这件事的资源门槛拉回到 100 MB 级。
  2. 单二进制 = 运维成本骤降:不用 JVM、不用配 vm.max_map_count、不用看 GC、不用调 heap size。新人 docker pull 后 5 分钟就有可用搜索。
  3. ES API 兼容意味着迁移成本低:已有用 _bulk / _doc 灌数据的代码可以改个 host 直接跑,不用重写客户端。
  4. 作者已转向 opensearch 之外的另一条路:2022-2023 同一个作者开了 OpenObserve 做日志可观测性。ZincSearch 现在是”搜索专用”,日志场景官方让你去用 OpenObserve。这个分流本身值得知道。

核心要点

ZincSearch 凭什么轻?拆三件事:

1. 用 Bluge 而不是 Lucene

elasticsearch 底层是 Lucene(Java 写的,跑在 JVM 上)。ZincSearch 底层是 Bluge——Marty Schoch 等人主导的 Bluge Labs 用 Go 重写的纯 Go 索引库,是 Bleve 的演进版(共用 Vellum 这个 FST 库)。

换语言带来的直接收益:

  • 没有 JVM = 没有几百 MB heap 起步价
  • 静态二进制 = 不用装运行时
  • Goroutine 模型 = 并发开销低于 JVM 线程

2. 单机,不做集群

ES 的复杂度一半来自分布式(分片、副本、coordinator、gossip)。ZincSearch 直接砍掉这一层——只跑单机,不做 HA。这是它能做小的根本原因。

代价:单机性能就是天花板。但对”中小数据量 + 应用内搜索”的场景来说,这天花板足够高。

3. 兼容 ES API 而不是重新发明

REST 接口照搬 ES 的 _bulk_doc_search 路径。DSL 查询语法部分兼容(标记 work-in-progress)。这意味着:

Terminal window
# 原来打到 ES 的 curl,改个 host 就能打到 ZincSearch
curl -X POST 'http://localhost:4080/api/_bulk' \
-H 'Authorization: Basic <token>' --data-binary @data.ndjson

迁移成本接近零,是 ZincSearch 拿用户的关键钩子。

实践案例

案例 1:docker 一行起服务

Terminal window
docker run -p 4080:4080 \
-e ZINC_FIRST_ADMIN_USER=admin \
-e ZINC_FIRST_ADMIN_PASSWORD=Pass123 \
public.ecr.aws/zinclabs/zincsearch:latest

跑完访问 localhost:4080,自带 Vue Web UI 登录页。对比 elasticsearch 首次启动要改 vm.max_map_count、设密码、调 heap,差距明显。

案例 2:灌一批文档(ES 兼容 _bulk)

Terminal window
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'

不用先 PUT mapping。schema-less,字段类型自动推断。

案例 3:搜索

Terminal window
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"}}'

返回 JSON 结构和 ES 类似但不完全一样——native API 是 ZincSearch 自己的 schema,DSL 兼容层只覆盖常用查询。

案例 4:内存占用对比

同样灌 100 万条 1KB 文档:

引擎常驻 RSS启动时间
elasticsearch 8.x1.5-2 GB(默认 heap)30-60 秒
ZincSearch v0.480-150 MB< 2 秒

数字会随负载浮动,但量级差是稳定的。这就是”个人项目 / 边缘节点”选 ZincSearch 而不是 ES 的核心理由。

踩过的坑

  1. DSL 兼容是 work-in-progress:复杂查询(nested、has_child、function_score、pipeline aggregation)大概率不工作。生产前用真实 query 跑一遍兼容性测试,别假设 ES 客户端原样能用。

  2. 没有集群 = 没有水平扩展:单机塞满就只能升配 / 拆 index / 上下游手动分流。数据涨到几百 GB 就该重新评估,回 elasticsearch / opensearch / meilisearch 集群版本。

  3. 作者重心已转 OpenObserve:v0.4.10(2024 年 1 月)后维护节奏变慢,issue 响应慢于早期。日志场景官方明说让你去用 OpenObserve,搜索场景社区维护。

  4. 磁盘存储无对象后端:默认本地磁盘,无内置 S3 / MinIO。要冷热分层、跨机共享需要自己在外面搭。OpenObserve 有 S3 后端,ZincSearch 没有。

  5. 聚合能力比 ES 弱一截:基础 terms / metric agg 可用;nested、pipeline、bucket script 这些 ES 高级聚合大概率不行。复杂 BI 场景别指望它。

适用 vs 不适用场景

适用

  • 应用内搜索 / 文档站搜索 / 博客搜索
  • 资源受限节点(边缘、树莓派、低配 VPS、Serverless 容器)
  • 中小数据量(< 100 GB)单机搜索
  • 已有 ES _bulk 客户端代码,想低成本换底层

不适用

历史

  • 2021 年:Prabhat Sharma 在 prabhatsharma/zinc 起项目,瞄准 ES 资源占用过重的真实痛点(自己跑业务搜索时受不了 JVM 的内存)
  • 2022 年:项目改名 ZincSearch,组织搬到 zincsearch/zincsearch,社区聚拢
  • 2022-2023 年:作者开 ZincObserve(后更名 OpenObserve)做日志可观测性,把”日志/指标/追踪”这条线从 ZincSearch 分出去
  • 2024 年 1 月:v0.4.10 发布,pre-GA。重心转 OpenObserve 后社区接手 ZincSearch 维护

整个轨迹很典型:先做对资源敏感的”小 ES 替代” → 发现日志和搜索是两件事 → 拆出独立产品。和 meilisearch 不同,MeiliSearch 是”开发者体验优先”路线,ZincSearch 是”资源占用优先”路线。

学到什么

  1. 重写不一定要做得更全,可以做得更小——ZincSearch 砍掉 ES 的分布式层,换语言换底层索引库,目标只有一个:把内存压到 1/10
  2. API 兼容是迁移最强的钩子——不重新发明协议,直接复用 ES 的 _bulk / _doc,迁移成本归零
  3. 底层换语言(Java → Go)= 静态二进制 + 无 GC 暖机 + 资源占用骤降——这条路 caddy(Web 服务器)、meilisearch(用 Rust)也走过
  4. 作者注意力是开源项目的隐性资源——ZincSearch 慢下来不是技术问题,是作者把精力投到 OpenObserve。读 GitHub 项目要看这个

延伸阅读

  • 官方文档:zincsearch-docs.zinc.dev
  • elasticsearch —— 工业标准对照,理解砍掉了什么
  • meilisearch —— 同代另一种”反 ES”路线(Rust + 开发者体验)
  • tantivy —— Rust 版 Lucene,Bluge 在 Go 生态里的对手

关联

  • elasticsearch —— 直接对标对象,理解砍了哪些功能
  • meilisearch —— 同样轻量化路线,但侧重开发者体验而非资源占用
  • opensearch —— ES 的 AWS fork,仍然重,与 ZincSearch 价值取向相反
  • tantivy —— Rust 版 Lucene,Bluge(ZincSearch 底层)是它在 Go 生态的同位
  • minisearch —— 浏览器内嵌入式搜索,比 ZincSearch 还小一截