Elasticsearch 核心原理与架构设计全解

3 阅读5分钟

一、 ES 是什么?为什么需要它?

1. 痛点:MySQL 的局限

在传统的关系型数据库(如 MySQL)中,如果我们执行模糊查询(LIKE '%关键词%'),索引会失效,导致全表扫描。当数据量达到百万级时,查询速度会急剧下降,甚至拖垮整个系统。

2. ES 的定位

Elasticsearch(简称 ES)是一个基于 Lucene 的分布式、RESTful 风格的搜索和分析引擎。

  • 核心价值:它解决了“海量数据下的全文检索”和“复杂多维分析”的性能问题。
  • 经典场景:电商商品搜索、日志分析(ELK)、监控预警。

二、 核心原理:倒排索引

ES 之所以快,核心在于倒排索引。这是它与 MySQL 最大的区别。

1. 正排索引

  • 逻辑:根据 ID 找内容。
  • 类比:书的目录,第 1 页是什么,第 2 页是什么。
  • MySQL 模式:存的是完整数据行,查询时需要逐行匹配。

2. 倒排索引

  • 逻辑:根据内容(词)找 ID。
  • 类比:书末尾的关键词索引页。查“自由”,索引页告诉你它出现在第 10、25 页。
  • 结构
    1. 词典:记录所有不重复的词。
    2. 倒排表:记录每个词出现在哪些文档 ID 中。

为什么叫“倒排”? 因为它把“文档 -> 词”的关系反转成了“词 -> 文档”,虽然听起来拗口,但却是搜索效率的来源。

为什么快?

  • 空间换时间:写入时消耗资源建立索引【耗时,耗性能】,查询时直接定位,无需遍历。
  • 内存利用:词典索引常驻内存,极快定位磁盘上的词典数据。

三、 架构设计:层级关系

ES 的架构分层非常清晰:集群 -> 节点 -> 分片 -> 段

1. 集群与节点

  • 节点:一个运行中的 ES 实例(一台服务器)。
  • 集群:多个节点的集合。
  • Master 节点:集群的大脑,负责管理元数据(创建索引、节点加入退出)。

2. 分片

  • 定义:数据的最小存储单元。一个索引的数据被切分成多个分片,分散在不同节点上。
  • 作用
    • 海量存储:单机存不下,分片让数据分散存储。
    • 并行计算:查询时,多台机器同时处理各自分片的数据,速度倍增。
  • 关键点:分片数量一旦确定,不可修改(类似分库分表)。
  • 路由算法shard_num = hash(doc_id) % num_primary_shards

3. Segment(段)

  • 定义:分片内部的数据文件,是不可变的。
  • 写入流程
    1. 数据先写入内存 Buffer。
    2. Refresh(默认 1 秒):Buffer 生成一个新的 Segment 文件。
    3. 结果:数据近实时可见(约 1 秒延迟)。
  • 段合并
    • 频繁写入会产生大量小 Segment,消耗文件句柄。
    • ES 后台线程自动将小 Segment 合并成大 Segment,并物理删除已标记删除的数据。

四、 数据存储与写入

1. Segment 内部结构

一个 Segment 包含:

  • 倒排索引:用于搜索(词典 + 倒排表)。
  • 正排索引:用于排序、聚合(ID -> 字段值)。
  • 源数据(_source):原始的 JSON 文档。
  • 删除标记:记录哪些 ID 被删除了。

2. 更新与删除的逻辑

由于 Segment 是不可变的,ES 不支持原地更新。

  • 删除:仅在 .del 文件中标记 ID 删除,查询时过滤掉。
  • 更新:标记旧文档删除 + 写入新文档。
  • 物理删除:在段合并时,真正剔除被标记的数据。

3. 写入代价

ES 写入开销极大(分词、建索引、段合并)。因此,ES 适合读多写少的场景。

  • 对于大字符串,如果不需搜索,务必设置 "index": false,避免无谓的分词开销。

五、 查询流程

当发起一个搜索请求时,ES 是分布式的:

  1. 协调节点:接收客户端请求的节点,负责转发和汇总。
  2. 广播:协调节点将请求转发给所有相关分片(主分片或副本分片)。
  3. 本地查询:各分片并行在本地 Segment 中查询(多线程),对结果排序,返回 Top N (ID + 分数) 给协调节点。
  4. 归并:协调节点汇总各分片结果,进行全局排序,取最终的 Top N。
  5. 取回:协调节点根据最终 ID,向分片获取完整文档 JSON,返回给客户端。

关于 Top N: 查 Top 10 时,每个分片只返回自己的前 10 条,汇总后排序。这种机制保证了性能,但也限制了深度分页(如查第 10 万条)的性能。


六、 分词与映射

1. 分词器

分词器决定了文本如何拆解为词典中的词。

  • 流程:字符过滤 -> 分词 -> 词过滤(转小写、去停用词)。
  • 中文支持:需安装 IK 分词器等插件。
  • 自定义词典:可手动添加新词(如“奥利给”),确保新词不被拆散,提高检索精度。

2. 映射

ES 如何知道哪些字段要建索引?

  • 动态映射:自动推断类型。
  • 显式映射:生产环境推荐,明确指定字段类型(text/keyword/integer)及是否索引。

七、 高可用与备份

1. 分片副本

  • 原理:每个主分片有若干副本分片,数据实时同步。
  • 分布:主分片和副本分片绝不在同一节点。
  • 容灾:节点挂了,副本自动提升为主分片,数据不丢失,服务不中断。

2. 集群备份

  • 方案:定期生成快照到远程存储(S3, HDFS)。

3. 脑裂问题

  • 网络波动导致集群分裂。需配置 minimum_master_nodes(过半数节点同意才能选主),防止数据不一致。

八、 ES vs MySQL vs ClickHouse

维度ElasticsearchMySQLClickHouse
核心场景全文检索、任意字段查询事务处理、精准查询海量数据分析、报表统计
查询速度毫秒级(倒排索引)简单查询快,模糊查询慢极快(列式存储)
写入性能较慢(重计算)较快极快(追加写入)
更新能力弱(标记删除)强(ACID)极弱
资源消耗极高(内存、磁盘)中等较高