cswork / 系统设计

第 32 章 / 共 57 章 · 约 3 分钟

关键技术:Elasticsearch

本页目录
  1. 1. 核心模型
  2. 2. 什么时候用
  3. 3. 什么时候不适合
  4. 4. 关键限制和数量级
  5. 5. 面试中常被追问的点
  6. 6. 和其他技术的取舍
  7. 7. 本站案例
  8. 章节测验

Elasticsearch 是建立在 Lucene 之上的分布式搜索引擎。它的核心是倒排索引:先把文本切成词,再记录每个词出现在哪些文档里,所以“包含这些词、按相关性排序”的查询很快。系统设计里一旦出现全文搜索、多条件筛选加排序、日志检索,基本都会把它放在主数据库旁边,作为一份可以重建的搜索副本。

1. 核心模型

  • 文档和索引:数据是 JSON 文档,存放在索引(index)里;mapping 定义每个字段怎么分词、怎么索引。
  • 倒排索引和分析器:分析器(analyzer)负责分词、转小写、词干还原、同义词。中文需要专门的分词器。
  • 相关性打分:默认用 BM25,结合词频和逆文档频率给文档打分,可以叠加业务权重(销量、时间衰减)。
  • 分片和副本:一个索引拆成若干主分片,每个主分片有副本。主分片数在建索引时确定,之后要改只能 split/shrink 或重建索引。
  • 近实时:写入的文档要等下一次 refresh(默认 1 秒)才能被搜到,所以写完立刻搜可能找不到。
  • 聚合:terms、range、date histogram 等,用来做分面筛选(facet)和统计。

2. 什么时候用

  • 全文搜索:商品、帖子、文档的关键词搜索,要求模糊匹配、同义词和相关性排序。
  • 多条件筛选加排序:“价格 100–300、四星以上、按销量排序”,再加每个筛选项的计数。
  • 自动补全:edge n-gram 或 completion suggester;规模很大时也会自己预计算前缀结果,见搜索自动补全案例。
  • 日志和可观测性:按时间写入大量日志,按关键字和字段检索、聚合。
  • 地理搜索:geo_distance 查询附近的店铺或活动。

3. 什么时候不适合

  • 当唯一的数据来源:没有多文档事务,写入后不是立刻可见,集群出问题时要能从主库重建。订单、账户这类数据的权威副本应该放在 PostgreSQL 之类的数据库里。
  • 简单的按 key 读取:按 id 查用户,数据库或缓存更快更便宜。
  • 同一文档的高频更新:每次更新都是标记删除旧文档、写入新文档,计数器这类字段频繁更新会产生大量合并开销。
  • 强一致读:刚写入就必须读到的场景,要么读主库,要么在写入时强制 refresh(代价高)。

4. 关键限制和数量级

维度要记住的事
分片大小常见建议是单个分片 10–50 GB;分片太多会让集群元数据和查询开销变大
可见延迟refresh 默认 1 秒;批量导入时可以调大,换取写入吞吐
深分页from + size 默认最多 10000 条(index.max_result_window);更深的翻页用 search_after
查询延迟常见查询几十毫秒;复杂聚合和通配符查询会慢很多
写入用 bulk API 批量写;单条写入吞吐低很多

5. 面试中常被追问的点

  • 索引和主库怎么保持同步? 不要在业务代码里“写库再写 ES”双写,两步中间失败就会不一致。更稳的做法是 CDC:数据库变更日志 → Kafka → 索引服务批量写入 ES;索引服务可以重放,出问题还能全量重建。
  • 为什么刚发的帖子搜不到? 近实时,要等 refresh;产品上可以把新内容先直接展示在作者自己的结果里。
  • 数据量增长后分片不够了怎么办? 用别名(alias)指向索引,按时间滚动建新索引(日志场景),或者建一个分片更多的新索引,重建完成后切换别名。
  • 相关性怎么调? 字段加权(标题比正文重要)、function score 叠加销量和新鲜度、离线评估点击率。
  • 热点和慢查询? 避免前置通配符、限制聚合的桶数、对高频查询做结果缓存。

6. 和其他技术的取舍

选项适合代价
Elasticsearch / OpenSearch全文搜索、分面、日志分析不是权威数据源;集群运维和容量规划要花精力
PostgreSQL 全文检索数据量不大、搜索需求简单,少一个组件相关性和扩展性有限
预计算的前缀索引 / Trie超高 QPS 的自动补全只适合固定的查询形态
向量数据库 / kNN语义相似搜索与关键词搜索互补,常常两者混合使用

7. 本站案例

章节测验

5 道选择题
  1. 商品写入数据库后,需要同步到 Elasticsearch。哪种做法最可靠?
  2. 用户发帖后立刻搜索自己的帖子却搜不到,最可能的原因是?
  3. 搜索结果页要支持用户翻到第 2000 页(每页 20 条),应该怎么做?
  4. 下面哪个需求最不应该交给 Elasticsearch?
  5. 日志索引的数据量持续增长,已有索引的主分片数不够用了。常见做法是?

章节讨论

正在加载讨论…