Elasticsearch一图流

Lucene 核心数据结构 (单机视角) Lucene 是如何通过倒排索引实现快速搜索,以及如何解决排序和存储问题的 graph TD subgraph Lucene_Segment ["Lucene Segment (最小索引单元/不可变)"] direction TB subgraph Inverted_Index ["倒排索引 (Inverted Index) - 用于搜索"] TI["Term Index (内存)"] TD["Term Dictionary (磁盘)"] PL["Posting List (磁盘)"] TI --"前缀索引/加速定位"--> TD TD --"关联文档ID"--> PL note1["> 举例: 查找 '小白'<br/>1. Term Index 定位大概位置<br/>2. Dictionary 找到 '小白'<br/>3. Posting List 得到 ID: [0, 1]"] style TI fill:#e1f5fe,stroke:#01579b style TD fill:#fff9c4,stroke:#fbc02d style PL fill:#fff9c4,stroke:#fbc02d end subgraph Storage ["数据存储"] SF["Stored Fields (行式存储)"] DV["Doc Values (列式存储)"] SF --"根据ID获取完整内容"--> Content["文档原始JSON"] DV --"用于排序/聚合"--> Sort["排序/聚合操作"] note2["> Stored Fields: 存完整数据<br/>> Doc Values: 空间换时间,优化排序"] style SF fill:#e8f5e9,stroke:#2e7d32 style DV fill:#f3e5f5,stroke:#7b1fa2 end end Query["搜索请求"] --> TI PL -.->|"得到文档ID"| Storage Elasticsearch 在Lucene基础上的分布式架构 架构图 graph Client["客户端应用"] --> Coord subgraph Cluster["Elasticsearch Cluster (集群)"] subgraph CoordLayer["协调节点(入口/分发/聚合)"] Coord["协调节点 (Coordinating)"] end subgraph MasterLayer["Master节点层(高可用选主)"] Master1["Master Node A"] Master2["Master Node B"] Master3["Master Node C"] end %% --- 核心改造:将分片物理挂载到 Data 节点下 --- subgraph DataLayer["Data节点层 (物理存储)"] subgraph Data1["Data Node 2"] P0["Primary Shard 0 (主)"] R1["Replica Shard 1 (副)"] end subgraph Data2["Data Node 1"] P1["Primary Shard 1 (主)"] R0["Replica Shard 0 (副)"] end end subgraph LuceneLayer["Lucene 底层引擎 (每个分片对应一套)"] subgraph SegP0["Segment (P0/R0 的底层)"] IIA["倒排索引-用于搜索"] TIA["Term Index-用于加速搜索"] SFA["Stored Fields-doc原始信息"] DVA["Doc Values-排序和聚合"] end subgraph SegP1["Segment (P1/R1 的底层)"] IIB["倒排索引"] TIB["Term Index"] SFB["Stored Fields"] DVB["Doc Values"] end end end %% === 连线逻辑 === %% 1. 请求流:客户端 -> 协调节点 -> 数据节点 Coord -- "1. 分发查询/写入" --> Data1 Coord -- "1. 分发查询/写入" --> Data2 %% 2. 主副分片同步(跨节点虚线) P0 -.->|"2. 数据同步"| R0 P1 -.->|"2. 数据同步"| R1 %% 3. 管理流:Master 管理 Data 节点 Master2 -.-|"集群元数据管理"| Data1 Master2 -.-|"集群元数据管理"| Data2 %% 4. 分片与底层引擎的关联 P0 -->|"读写调用"| SegP0 R0 -->|"读写调用"| SegP0 P1 -->|"读写调用"| SegP1 R1 -->|"读写调用"| SegP1 %% === 样式优化 === style Cluster fill:#f5f5f5,stroke:#333 style CoordLayer fill:#e3f2fd,stroke:#1565c0,stroke-dasharray: 5 5 style MasterLayer fill:#f3e5f5,stroke:#7b1fa2,stroke-dasharray: 5 5 style DataLayer fill:#e8f5e9,stroke:#2e7d32,stroke-dasharray: 5 5 %% 高亮主副分片颜色 style P0 fill:#ffcdd2,stroke:#b71c1c style P1 fill:#ffcdd2,stroke:#b71c1c style R0 fill:#bbdefb,stroke:#0d47a1 style R1 fill:#bbdefb,stroke:#0d47a1 style LuceneLayer fill:#fff3e0,stroke:#e65100 没有指定协调节点的时候,所有节点默认都具备协调节点功能 classDiagram class Cluster { +String cluster_name +List nodes } class Node { +String node_name +List roles +store_data() +coordinate_request() } class NodeRoles { Master Data Coordinating } note for NodeRoles "枚举类型 (Enumeration)<br/>Master: 集群管理<br/>Data: 数据存储<br/>Coordinating: 请求转发" class Index { +String index_name +List shards } class Shard { +int shard_id +LuceneInstance underlying_engine } class PrimaryShard { +sync_to_replica() } class ReplicaShard { +promote_to_primary() } class LuceneInstance { +List segments +merge_segments() } class Segment { +InvertedIndex +StoredFields +DocValues +is_immutable } Cluster *-- Node Node ..> NodeRoles : 扮演角色 Index *-- Shard Shard <|-- PrimaryShard Shard <|-- ReplicaShard Shard *-- LuceneInstance : 底层引擎 LuceneInstance "1" *-- "*" Segment : 包含多个 Node "1" o-- "*" Shard : 承载 note for PrimaryShard "负责写入,同步数据给副本" note for ReplicaShard "提供读能力,主分片挂掉后升级" note for Node "单节点可扩展为多节点集群<br/>通过 Raft 类机制选主" note for LuceneInstance "写入产生新Segment<br/>后台定期合并小Segment<br/>以优化文件句柄和查询性能" 从 Lucene 到 Elasticsearch 的演进 Lucene 作为一个单纯的搜索库,虽然功能强大,但在面对海量数据和高并发场景时存在明显的单机局限性: ...

2024/11/06 · 5 分钟 · 2349 字 · Aris