跳转到内容

Elasticsearch — 分布式搜索引擎

待复核

Elasticsearch 是一个基于 lucene 构建的”分布式 + RESTful API + JSON”搜索引擎

日常类比:

  • postgresql 像图书馆按编号查书——你必须知道这本书在哪个架、哪一行
  • Elasticsearch 像 Google 搜索引擎——你输入关键词,它返回所有相关书籍,并按”相关程度”打分排序

它不是要替代关系型数据库,而是补全它的弱项:全文搜索、模糊匹配、海量日志聚合、多维度过滤。Postgres 也能做 LIKE 查询,但一旦数据量上千万行、查询带模糊匹配 + 排序 + 聚合,Postgres 就吃力,而 Elasticsearch 的倒排索引天生为这种场景设计。

下面这些场景,Elasticsearch 是常见默认选型之一:

  • 大型应用日志 / 站内搜索:GitHub、Stack Overflow、Wikipedia 等站点曾用或仍在用它做搜索与日志检索(具体栈会随年代变)
  • 全文检索 + 评分排序:电商搜索”iPhone 13 256G 黑”要按相关度排,关系库做起来很吃力
  • 可观测性(运维监控):ELK Stack(Elasticsearch + Logstash + Kibana)是开源运维监控常见组合
  • 8.x 后内置向量搜索:可以存 embedding 做语义搜索,与 Pinecone / Milvus 这类专门向量库正面竞争
  • 2021 SSPL 许可争议:Elastic 把许可从 Apache 2.0 改成 SSPL,AWS fork 出 OpenSearch——影响了之后开源数据库圈的许可证选择

理解 Elasticsearch 抓三个概念就够:

普通索引:从”文档 ID”找”内容”。倒排索引:从”词”找”哪些文档包含这个词”。

类比:书末尾的”索引页”,告诉你”分布式”这个词出现在哪些章节。Elasticsearch 把这种结构做到极致——任何字段建索引后都能毫秒级查”包含某词的全部文档”。

每个 index(类似数据库里的表)默认切成多个 shard,自动分布到集群的多台机器上。每个 shard 还可以有副本(replica)做容灾。

  • shard 决定水平扩展能力:数据多了加机器就行
  • replica 决定可用性:主 shard 挂了,副本顶上

用嵌套 JSON 表达复杂查询条件 + 聚合,叫 Query DSL。比 SQL 更适合”模糊 + 多条件 + 聚合”组合,但学习曲线比 SQL 陡。

案例 一:本地启一个单节点集群

Section titled “案例 一:本地启一个单节点集群”
Terminal window
docker run -p 9200:9200 -e discovery.type=single-node \
-e xpack.security.enabled=false \
elasticsearch:8.11.0

discovery.type=single-node 告诉它”不要去找其他节点”,否则它会一直等集群成员。xpack.security.enabled=false 关掉认证(仅本地玩具用)。

PUT /products/_doc/1
Content-Type: application/json
{
"name": "iPhone 13",
"price": 999,
"tags": ["phone", "apple"]
}

/products 是索引名(相当于表);/_doc/1 是文档 ID。Elasticsearch 自动推断字段类型(name → text,price → long,tags → keyword 数组),这叫动态 mapping

POST /products/_search
Content-Type: application/json
{
"query": {
"match": { "name": "iPhone" }
}
}

返回结果里每个文档都有一个 _score——这就是”相关度评分”,由 BM25 算法算出(默认)。match 会对查询词做分词,所以搜 “iphone 13 black” 能匹配到 “iPhone 13” 文档。

字段一旦确定是 textlong改不了。要改只能:

  1. 新建一个空 index,用对的 mapping
  2. _reindex API 把旧数据全量复制过去
  3. 切换别名指向新 index

新人最容易踩——动态 mapping 把字段推断错了,几个月后才发现,数据已经几亿条。

number_of_shards 在 index 创建时定,之后改不了。设小了没法水平扩展,设大了每个 shard 太小浪费资源。生产经验:单 shard 控制在 10-50GB,按预期数据量算 shard 数。

JVM heap 默认 1G,生产环境至少 16-32G。但不要超过 32G——超过后 JVM 失去 compressed oops 优化反而更慢。机器物理内存的另一半留给 Lucene 的文件系统缓存(Lucene 大量使用 mmap)。

慢日志和热索引混在一起影响性能

Section titled “慢日志和热索引混在一起影响性能”

把”慢的写入密集型 index”(比如日志)和”快的查询密集型 index”(比如商品搜索)放同一个集群,互相影响。最佳实践:分集群 —— logging 集群和 search 集群独立。

适用

  • 全文搜索 / 模糊匹配 / 相关度排序(百万~百亿文档级常见)
  • 日志与可观测性检索(ELK),写入吞吐高、查询以过滤+聚合为主
  • 需要近实时索引(秒级可见),可接受最终一致而非跨文档事务

不适用

  • 需要多行事务 / 强一致主键更新 → 用 postgresql
  • 只要精确 KV 快读 → 用 redis
  • 数据量很小(万级)且只要简单 LIKE → 关系库或 meilisearch 更轻
  • 2010 年:Shay Banon 给妻子做菜谱搜索时,对 Lucene 做了分布式封装,开源命名为 Elasticsearch
  • 2012 年:Elastic 公司成立,商业化
  • 2018 年:Elastic 上市 IPO(NYSE: ESTC)
  • 2021 年:许可证从 Apache 2.0 改成 SSPL,不再算 OSI 意义下的”开源”
  • 2021-04:AWS fork 出 OpenSearch(保留 Apache 2.0),社区分裂
  • 2024 年:Elasticsearch 8.x 主推向量搜索 + 内置 ML 模型(ELSER)做语义搜索
  1. 关系库 + 搜索引擎是互补关系:写入和事务靠关系库(Postgres),查询和聚合靠搜索引擎(Elasticsearch)。常见架构是 Postgres 写主存储 → CDC(变更数据捕获)同步到 Elasticsearch
  2. 倒排索引是搜索引擎的命根子:理解它就理解 80% 的搜索引擎设计
  3. shard / replica 是分布式系统的通用语言mongodb / cassandra / Kafka 的设计哲学一样
  4. 开源许可证是商业战略:SSPL 之争之后,Redis / MongoDB / Confluent 都跟进改许可,云厂商也都做了 fork,整个生态都被影响
  • 官方文档:Elasticsearch Guide
  • 许可分叉对照:opensearch —— AWS 主导的 Apache 2.0 分叉
  • 轻量替代:meilisearch / typesense —— 开发者友好的搜索引擎
  • 底层引擎血缘:Lucene 倒排索引与 BM25 评分(Elasticsearch 的地基)
  • opensearch —— 2021 许可变更后的 Apache 2.0 分叉,运维概念高度同构
  • meilisearch —— 更轻的搜索引擎,适合中小站内搜
  • postgresql —— 主存储常用关系库;和 Elasticsearch 是互补不是替代
  • redis —— 同样常和 Postgres 搭配,但解决的是”快读取”不是”全文搜索”
  • kafka —— 日志管道里常作 Logstash/Beats 上游缓冲
  • typesense —— 另一条高性能搜索引擎路线,对照选型
  • croft-harper-1979 —— Croft-Harper 1979 — 没有相关性反馈也能跑概率检索
  • milvus-2021 —— Milvus 2021:把向量搜索做成数据库
  • opensearch —— OpenSearch — AWS 主导的 Apache 2.0 搜索引擎分叉
  • druid —— Apache Druid — 流批一体的实时分析数据库
  • grafana —— Grafana — 监控可视化看板
  • jaeger —— Jaeger — 分布式追踪系统
  • loki —— Loki — 给日志做 Prometheus,只索引标签不索引内容
  • manticoresearch —— Manticore Search — 用 MySQL 协议连的搜索 + OLAP 引擎
  • meilisearch —— MeiliSearch — 开发者友好的搜索引擎
  • minisearch —— minisearch — 浏览器里的小型全文搜索引擎
  • neo4j —— Neo4j — 主流图数据库
  • opensearch —— OpenSearch — AWS 主导的 Apache 2.0 搜索引擎分叉
  • pino —— pino — 日志不该阻塞热路径
  • pouchdb —— PouchDB — 浏览器里的 CouchDB
  • prometheus —— Prometheus — 时序监控系统
  • ravendb —— RavenDB — .NET 生态首选的 ACID 文档数据库
  • sonic —— Sonic — 极简前缀搜索引擎
  • tantivy —— Tantivy — Rust 版 Lucene
  • typesense —— Typesense — 高性能搜索引擎
  • vector —— Vector — Rust 写的统一可观测性数据管道
  • vespa —— Vespa — Yahoo 检索 + 排序引擎
  • zincsearch —— ZincSearch — 单二进制 Go 写的 ES 替代