核心思想是在多台机器上启动多个ES进程实例,组成一个ES集群。ES中存储数据的基本单位是索引,用来存储具有共同特性的文档集合,一个索引差不多就相当于Mysql中的表。为了提高可伸缩性和容错性,ES会将索引划分为多个分片,每个分片都是一个独立的Lucene索引,可以部署在集群中的任何节点上,一个索引包含一个或多个主分片和零个或多个副本分片,主分片负责数据的写入,而副本分片则用于数据的容错和读请求的分流。
- 索引(Index)
类似数据库中的“表”,是文档的逻辑集合。每个索引有一个唯一的名称(如products)
- 文档(Document)
索引中的基本数据单元,以JSON格式存储;每个文档有一个唯一ID和类型
- 分片(Shard)
索引被水平拆分的子集,每个分片是一个独立的Lucene索引;
主分片:数据写入的目标分片,数量在索引创建时固定
副本分片:主分片的拷贝,提供高可用和读负载均衡
- 节点(Node)
一个运行的ES实例,可以是数据节点、主节点或协调节点
- 客户端请求:文档发送到协调节点
- 路由与分片选择:协调节点根据文档ID的哈希值选择目标分片
- 写入主分片:主分片先写入内存缓冲区,同时记录到事务日志(用于崩溃恢复)
- 刷新:默认1秒,内存缓冲区的内容生成一个新的段(Segment)并开放搜索
- 刷盘:定期将内存中的段持久化到磁盘
- 同步副本:主分片将写入操作同步到所有副本分片
- 倒排索引:核心数据结构,记录每个词项出现在哪些文档中
- 分词:将文本转换为词项的过程
查询流程:
- 对查询字符串分词(使用相同的分析器)。
- 在倒排索引中匹配词项,计算相关性得分(如 TF-IDF、BM25)。
- 返回排序后的文档。
- 索引设计:
- 合理设置分片数(建议单个分片大小 10-50GB)。
- 使用
routing将相关文档存到同一分片,减少跨分片查询。
- 查询优化:
- 避免
wildcard查询(性能差),改用keyword类型 + 前缀搜索。 - 使用
filter替代query条件(不计算得分,结果可缓存)。
- 避免
- 硬件与配置:
- 数据节点使用 SSD,内存分配给文件系统缓存(建议不超过 50% 堆内存)。
- 调整
indices.query.bool.max_clause_count解决大量terms查询问题。
- 聚合优化:
- 对高基数字段(如用户 ID)使用
cardinality聚合时,开启precision_threshold。
- 对高基数字段(如用户 ID)使用