Elasticsearch介绍
Elasticsearch(ES)的工作原理可以高度概括为“分布式、倒排索引、近实时搜索”。
1. 核心基石:倒排索引(Inverted Index)
这是ES搜索飞快的根本原因。不同于传统数据库(正排索引:ID -> 内容),倒排索引是内容 -> ID。
例子:你有三篇文档。
文档1:
"苹果好吃"文档2:
"香蕉好吃"文档3:
"苹果营养"
倒排索引构建:
苹果-> [文档1, 文档3]好吃-> [文档1, 文档2]营养-> [文档3]
查询时:当你搜索“苹果”,ES直接命中索引,瞬间返回文档1和3,不需要扫描所有数据。
2. 数据写入流程(Index / Write)
ES写入并不是直接写磁盘,而是走Memory Buffer -> Filesystem Cache -> Segment -> Commit的路线,这是它近实时(Near Real-Time)的关键。
写入内存缓冲区(Buffer):数据到达时,先写入
Transaction Log(防止宕机丢数据),同时将原始JSON文档放入内存Buffer中,此时数据不可被搜索。Refresh(刷新):默认每隔1秒,ES会执行Refresh操作,将Buffer中的数据冲刷到操作系统的文件缓存(Filesystem Cache)中,并生成一个新的分段(Segment)。
关键点:此时数据已经可以搜索,但尚未落盘(Fsync)。这就是ES被称为“近实时”(延迟1秒)的原因。
Flush(冲刷):当Translog太大或每隔30分钟,ES会执行Flush。将所有内存中的Segment刷入磁盘,并清空Translog。此时数据才算真正持久化。
3. 数据读取流程(Search / Read)
ES的读取分为Query Phase(查询阶段)和Fetch Phase(取回阶段),且利用分片(Shard)并行工作。
假设你有3个节点,索引被分为2个主分片(Primary)和2个副本分片(Replica)。
Query Phase:协调节点(Coordinating Node)收到搜索请求,会将请求广播给所有分片(主或副本)。每个分片在本地利用倒排索引找到匹配的文档ID,但只返回文档ID和评分给协调节点。协调节点对全局所有ID进行合并排序。
Fetch Phase:协调节点根据排好序的ID列表,再次请求各个分片,获取文档的完整原始
_source数据,返回给客户端。
4. 核心底层数据结构
为了让倒排索引更快,ES使用了以下核心编码技术:
FST(Finite State Transducer,有限状态转换器):用于存储词典(Term Dictionary),内存占用极小,查询速度极快(O(1)级别)。
跳跃表(Skip List):用于在多个Posting List(文档ID列表)之间快速求交集(AND)或并集(OR)。
BKD Tree:用于数值类型和地理位置的范围查询(Range Query),而非倒排索引。
5. 分布式架构原理(去中心化)
Master Node(主节点):只负责管理集群状态(创建索引、分配分片),不参与数据读写,防止脑裂。
数据节点(Data Node):负责存储数据和执行实际的搜索计算。
路由算法:当你写入一条数据时,ES通过公式
shard_num = hash(_routing) % number_of_primary_shards决定该数据去哪个分片,保证同一文档永远在固定分片,方便查询时定位。
6. 你必须要知道的“坑”(面试重点)
删除不是真删除:ES的删除只是给文档打上
deleted标记,在Segment Merge时才会物理清除,所以频繁删除会导致性能下降。Segment是不可变的:一旦写磁盘就永不改变。ES通过后台
Merge进程将多个小Segment合并成大Segment,释放被标记删除的空间,这也是写性能高的原因(没有锁竞争)。
一句话总结
Elasticsearch 通过“倒排索引”实现快速匹配,通过“内存Buffer + 每秒Refresh”实现近实时搜索,通过“分片 + 副本”实现高可用和水平扩展,通过“Segment合并”实现后台异步持久化。
