Skip to content
Gains Summary
Main Navigation 首页 / Home
C++ 编程 / C++ Programming
系统与高性能 / Systems & Performance
Web 开发 / Web Development
人工智能 / Artificial Intelligence
工业软件 / Industrial Software
其他内容 / Other Topics
C++ 编程 / C++系统与性能 / SystemsWeb 开发 / Web人工智能 / AI工业软件 / Industrial

外观

Sidebar Navigation

← Web 开发 / Web Development

中间件 / Middleware

1. Web 中间件全景 / The Web Middleware Landscape

2. 中间件——流量洪峰下的系统保护 / Middleware for Protecting Systems Under Traffic Spikes

cache layer

1. 缓存架构全景 / Cache Architecture Overview

2. Redis 深入——为什么你的缓存总是出问题 / Redis Internals and Cache Failure Modes

3. Redis 数据结构场景应用——什么时候用什么 / Choosing Redis Data Structures for Real Applications

4. 缓存策略——库存变了,缓存怎么处理 / Cache Strategies and Inventory Consistency

5. Redis 缓存三剑客——穿透/击穿/雪崩 + 一致性策略 / Redis Cache Penetration, Breakdown, Avalanche, and Consistency

6. Redis 分布式锁——从 SETNX 到 Redisson / Redis Distributed Locks from SETNX to Redisson

7. Redis Cluster 与 Sentinel 高可用架构 / Redis Cluster and Sentinel High-Availability Architecture

8. Redis 高级特性——Stream / PubSub / Module / LLM 应用

9. Redis 架构深度分析——为什么 Redis 能这么快 / Redis Architecture and the Sources of Its Performance

10. Redis 全景——为什么你的系统需要一个缓存层 / The Redis Landscape and Why Systems Need a Cache Layer

message queue

1. 消息队列全景——为什么你的系统需要一个中间人 / Message Queue Overview and Why Your System Needs a Middleman

2. Kafka 核心——为什么你的消息总是"丢"了 / Kafka Fundamentals and Message Delivery Semantics

3. 消息队列高级——死信队列、延迟消息、消息积压 / Advanced Messaging with Dead Letters, Delays, and Backlogs

4. Kafka Streams 与 Connect —— 让数据自己流动起来 / Kafka Streams and Connect for Streaming Data Pipelines

5. RabbitMQ 深度解析 —— 灵活路由与消息可靠性 / RabbitMQ Deep Dive into Flexible Routing and Reliability

6. 消息队列对比——为什么最终选了 Kafka / Comparing Message Queues and Choosing Kafka

search engine

1. 搜索引擎知识体系 / Search Engine Knowledge System

2. Elasticsearch——为什么 Like 查询总是那么慢 / Elasticsearch for Full-Text Search at Scale

3. Elasticsearch 查询 DSL 深入——为什么你的搜索总是不准 / Elasticsearch Query DSL Deep Dive

4. Elasticsearch 集群规划与运维——为什么你的集群总是"黄" / Elasticsearch Cluster Planning and Operations

5. Meilisearch 与轻量搜索替代方案——当 ES 太重时 / Meilisearch and Lightweight Search Alternatives

infrastructure

1. 基础设施组件全景 / Infrastructure Components Landscape

2. Nginx 与反向代理 / Nginx and Reverse Proxy

3. 服务发现 / Service Discovery

4. 配置中心 / Configuration Center

本页目录

Elasticsearch 集群规划与运维——为什么你的集群总是"黄" / Elasticsearch Cluster Planning and Operations ​

📅 创建时间:2026-07-28 🏷️ 标签:#Elasticsearch #集群 #分片策略 #集群运维 #性能调优 #高可用 📚 前置知识:[[./00-overview]](搜索引擎概览) [[./02-elasticsearch-queries]](ES 查询 DSL)


📋 本章目标 ​

  • 理解 ES 集群的四种节点角色及其职责分工
  • 掌握主分片与副本分片的策略:数量计算、过分配问题、动态扩展
  • 理解写入流程的全链路:refresh → flush → translog → 近实时搜索
  • 能够诊断集群健康状态:Green / Yellow / Red 的含义与排查
  • 掌握集群运维操作:滚动重启、快照备份、跨集群复制 CCR
  • 理解性能调优的核心参数:heap 设置、bulk 写入优化、查询缓存

第1部分:集群架构 ​

1.1 ES 集群的物理拓扑 ​

┌─────────────────────────────────────────────────────────────┐
│                    ES 集群物理拓扑                            │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  ┌─────────────────────────────────────────────────────┐   │
│  │                     ES Cluster "search-prod"         │   │
│  │                                                     │   │
│  │  ┌──────────────┐  ┌──────────────┐  ┌───────────┐ │   │
│  │  │   Node 1     │  │   Node 2     │  │  Node 3   │ │   │
│  │  │  ┌────────┐  │  │  ┌────────┐  │  │ ┌───────┐ │ │   │
│  │  │  │Shard P0│  │  │  │Shard R0│  │  │ │Shard P1│ │ │   │
│  │  │  │(主分片)│  │  │  │(副本0) │  │  │ │(主分片)│ │ │   │
│  │  │  └────────┘  │  │  └────────┘  │  │ └───────┘ │ │   │
│  │  │  ┌────────┐  │  │  ┌────────┐  │  │ ┌───────┐ │ │   │
│  │  │  │Shard R1│  │  │  │Shard P2│  │  │ │Shard R2│ │ │   │
│  │  │  │(副本1) │  │  │  │(主分片)│  │  │ │(副本2) │ │ │   │
│  │  │  └────────┘  │  │  └────────┘  │  │ └───────┘ │ │   │
│  │  └──────────────┘  └──────────────┘  └───────────┘ │   │
│  │                                                     │   │
│  │  主分片 P0、P1、P2 → 各存 1/3 数据(唯一数据源)    │   │
│  │  副本分片 R0、R1、R2 → 完整数据备份                  │   │
│  │  任意一个节点挂掉,数据不丢,服务不中断              │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
│  关键概念:                                                 │
│  • 一个 Index 的数据被水平切分成多个 Shard(主分片)       │
│  • 每个主分片可以有 0-N 个 Replica(副本分片)             │
│  • 主分片和副本分片永远不会在同一个节点上                  │
│  • 写操作先到主分片,再由主分片同步到副本分片              │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

1.2 节点角色详解 ​

┌─────────────────────────────────────────────────────────────┐
│                    四种节点角色                               │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  Master Node(主节点)                                │   │
│  │  ┌──────────────────────────────────────────────┐   │   │
│  │  │  职责:集群管理,不处理查询和写入               │   │   │
│  │  │  • 创建/删除 Index                              │   │   │
│  │  │  • 分配 Shard 到节点                           │   │   │
│  │  │  • 节点加入/离开集群                            │   │   │
│  │  │  • 维护集群状态(Cluster State)               │   │   │
│  │  │                                              │   │   │
│  │  │  配置:node.roles: [master]                    │   │   │
│  │  │  数量:3 个(专用节点,小集群可兼 data)       │   │   │
│  │  │  资源:轻量,CPU/内存需求低                    │   │   │
│  │  └──────────────────────────────────────────────┘   │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  Data Node(数据节点)                                │   │
│  │  ┌──────────────────────────────────────────────┐   │   │
│  │  │  职责:存储数据,执行查询和聚合                 │   │   │
│  │  │  • 存储 Shard 数据                             │   │   │
│  │  │  • 执行搜索、聚合、写入操作                    │   │   │
│  │  │  • 消耗最多的 CPU、内存、磁盘 IO              │   │   │
│  │  │                                              │   │   │
│  │  │  配置:node.roles: [data]                     │   │   │
│  │  │  数量:与数据量成正比,通常 3-几十个           │   │   │
│  │  │  资源:大内存(31GB heap 以下)、SSD 必须     │   │   │
│  │  │                                              │   │   │
│  │  │  子角色(ES 7.x+):                           │   │   │
│  │  │  • data_content: 内容数据(默认)             │   │   │
│  │  │  • data_hot: 热数据(频繁读写)               │   │   │
│  │  │  • data_warm: 温数据(偶尔读)                │   │   │
│  │  │  • data_cold: 冷数据(很少读)                │   │   │
│  │  │  • data_frozen: 冻结数据(几乎不读)          │   │   │
│  │  └──────────────────────────────────────────────┘   │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  Ingest Node(摄取节点)                              │   │
│  │  ┌──────────────────────────────────────────────┐   │   │
│  │  │  职责:文档写入前的预处理                       │   │   │
│  │  │  • 执行 Ingest Pipeline(字段转换、丰富)     │   │   │
│  │  │  • 不存储数据                                  │   │   │
│  │  │  • 降低 Data Node 的 CPU 负担                 │   │   │
│  │  │                                              │   │   │
│  │  │  配置:node.roles: [ingest]                   │   │   │
│  │  │  使用场景:大量写入需要预处理时                │   │   │
│  │  └──────────────────────────────────────────────┘   │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  Coordinating Node(协调节点)                       │   │
│  │  ┌──────────────────────────────────────────────┐   │   │
│  │  │  职责:请求路由和结果合并                       │   │   │
│  │  │  • 接收客户端请求                              │   │   │
│  │  │  • 分发查询到各 Data Node                       │   │   │
│  │  │  • 合并和排序结果                               │   │   │
│  │  │  • 不存储数据,不处理主节点事务                │   │   │
│  │  │                                              │   │   │
│  │  │  配置:所有角色都设为 false                     │   │   │
│  │  │  使用场景:大集群需要独立的查询负载均衡层       │   │   │
│  │  └──────────────────────────────────────────────┘   │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68

1.3 集群拓扑演进:从小到大的部署模式 ​

┌─────────────────────────────────────────────────────────────┐
│                    集群拓扑演进路线                           │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  Level 1: 单节点(开发/测试)                               │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  Node: master + data + ingest (全角色)              │   │
│  │  分片: 1 primary, 0 replica                         │   │
│  │  适用: 本地开发,数据可丢                            │   │
│  └─────────────────────────────────────────────────────┘   │
│         ↓ 上生产                                            │
│  Level 2: 三节点(小型生产)                               │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  3 nodes: master + data + ingest (全角色)           │   │
│  │  分片: 1 primary, 1 replica (共2份拷贝)             │   │
│  │  最小 master 节点数 = 3 (防脑裂)                    │   │
│  │  适用: 小型搜索服务,数据 < 100GB                   │   │
│  └─────────────────────────────────────────────────────┘   │
│         ↓ 业务增长                                          │
│  Level 3: 数据与主节点分离(中型生产)                     │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  3 master nodes (专用) + 5 data nodes               │   │
│  │  分片: 3 primary, 1 replica                         │   │
│  │  适用: 数据 100GB-1TB,查询 QPS > 100              │   │
│  └─────────────────────────────────────────────────────┘   │
│         ↓ 大规模                                            │
│  Level 4: 全角色分离 + 冷热分层(大型生产)               │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  3 master + 2 coordinating + 2 ingest              │   │
│  │  + 6 hot data nodes (SSD) + 4 warm data nodes (HDD)│   │
│  │  分片: 5 primary, 1 replica                         │   │
│  │  适用: 数据 > 1TB,高并发读写,日志分析等           │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

第2部分:分片策略 ​

2.1 分片数量计算 ​

┌─────────────────────────────────────────────────────────────┐
│                    分片数量决策矩阵                           │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  主分片数量 = f(数据量, 写入QPS, 查询QPS, 节点数)          │
│                                                             │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  维度             计算公式 / 经验值                  │   │
│  │  ─────────────────────────────────────────────       │   │
│  │  数据量 (GB)      每个分片 10-50GB(推荐 30GB)     │   │
│  │                   分片数 ≈ 总数据量 / 30             │   │
│  │                                                      │   │
│  │  写入吞吐          每个分片处理约 1-2 万 docs/s     │   │
│  │                                                      │   │
│  │  查询性能          每个 CPU 核心 1-2 个分片          │   │
│  │                                                      │   │
│  │  堆内存 (Heap)     每 1GB heap → 20 个分片           │   │
│  │                    (每个分片约占 50MB heap)           │   │
│  │                                                      │   │
│  │  ES 限制           每个节点最多 1000 个分片           │   │
│  │                    每个索引最多 1024 个分片           │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
│  案例计算:                                                 │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  场景:商品搜索,当前数据 10GB,预计 1 年增长到     │   │
│  │        200GB,3 个数据节点(每节点 4 核 16GB RAM)  │   │
│  │                                                      │   │
│  │  数据量约束: 200GB / 30GB ≈ 7 个分片                │   │
│  │  Heap 约束:  16GB heap × 20 = 320 个分片上限        │   │
│  │  CPU 约束:   3×4=12 核,12×2=24 个分片上限          │   │
│  │                                                      │   │
│  │  推荐:5-10 个主分片,1 个副本分片                   │   │
│  │  预留了未来扩展空间,同时保持查询性能                │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

2.2 过分配问题 ​

┌─────────────────────────────────────────────────────────────┐
│                    分片过多 vs 过少的代价                     │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  分片过多的代价(更常见、更致命):                          │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  • 每个分片消耗内存(约 50MB heap)                  │   │
│  │    1000 个分片 × 50MB = 50GB heap(很容易 OOM)    │   │
│  │                                                      │   │
│  │  • 每次查询需要广播到所有分片                         │   │
│  │    100 个分片 = 100 次内部网络请求                   │   │
│  │    协调节点合并 100 个结果 = CPU 瓶颈                │   │
│  │                                                      │   │
│  │  • 集群状态 (Cluster State) 增大                     │   │
│  │    分片越多,Master 维护的元数据越多,更新越慢       │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
│  分片过少的代价:                                           │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  • 无法利用多节点并行能力                             │   │
│  │  • 单个分片过大(>100GB)导致 rebalance 极慢         │   │
│  │  • 后续无法增加分片数(主分片数量不可变)            │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
│  黄金法则:                                                 │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  1. 分片大小:10-50GB(目标 30GB)                   │   │
│  │  2. 分片数量:数据节点 CPU 核心数 × 1.5 ~ 3         │   │
│  │  3. 宁可稍多,不要过少(分片少无法扩展)            │   │
│  │  4. 预留 20% 增长空间                                │   │
│  │  5. 使用 Rollover + Index Lifecycle Management      │   │
│  │     按时间切分索引,而不是无限扩大单个索引           │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

2.3 Shard 分配策略 ​

┌─────────────────────────────────────────────────────────────┐
│                    Shard 分配感知                             │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  ES 支持多种分配感知 (Allocation Awareness),保证副本      │
│  不会落在同一故障域:                                       │
│                                                             │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  Rack Awareness(机架感知)                           │   │
│  │  node.attr.rack: rack1 / rack2 / rack3              │   │
│  │  → 主分片和副本分片不会放在同一机架                   │   │
│  │                                                      │   │
│  │  Zone Awareness(可用区感知,云环境)                 │   │
│  │  node.attr.zone: zone-a / zone-b / zone-c           │   │
│  │  → 副本分片分配在不同可用区                           │   │
│  │                                                      │   │
│  │  Shard Filtering(分片过滤)                          │   │
│  │  "index.routing.allocation.include.zone": "zone-a"  │   │
│  │  → 强制某个索引的分片只在特定节点上                   │   │
│  │  → 热温冷数据分层的关键配置                           │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
│  强制感知配置:                                             │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  cluster.routing.allocation.awareness.attributes:    │   │
│  │    rack, zone                                         │   │
│  │  cluster.routing.allocation.awareness.force.zone:    │   │
│  │    true  ← 如果无法满足 zone 感知,分片不分配        │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

第3部分:写入流程 ​

3.1 从写入请求到可搜索的完整链路 ​

┌─────────────────────────────────────────────────────────────┐
│                    写入流程全链路                             │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  客户端                                                      │
│     │ POST /products/_doc/1                                 │
│     ▼                                                       │
│  Coordinating Node                                          │
│     │ 1. 根据 _routing (默认 _id) 计算目标 shard            │
│     │    shard_num = hash(_routing) % num_primary_shards    │
│     ▼                                                       │
│  Primary Shard (Node A)                                    │
│     │                                                       │
│     │ 2. 写入 Translog(先写 WAL,保证不丢)               │
│     │    ┌───────────────────────────────────────────┐     │
│     │    │  Translog (Write-Ahead Log)               │     │
│     │    │  • 顺序写入,磁盘 fsync                   │     │
│     │    │  • 节点崩溃后用于恢复未 flush 的数据       │     │
│     │    │  • 类似于 MySQL 的 binlog                 │     │
│     │    └───────────────────────────────────────────┘     │
│     │                                                       │
│     │ 3. 写入 In-Memory Buffer(内存缓冲区)               │
│     │    ┌───────────────────────────────────────────┐     │
│     │    │  In-Memory Buffer                         │     │
│     │    │  • 最新文档的倒排索引先存在内存            │     │
│     │    │  • 此时文档还不可搜索!                    │     │
│     │    └───────────────────────────────────────────┘     │
│     │                                                       │
│     │ 4. 转发到 Replica Shards                              │
│     │    → 每个 replica 重复步骤 2-3                       │
│     │                                                       │
│     ▼                                                       │
│  ┌─────────────────────────────────────────────────────┐   │
│  │                    定时 Refresh (默认 1s)           │   │
│  │                                                     │   │
│  │  5. 将 In-Memory Buffer 中的文档写入 Segment        │   │
│  │     ┌───────────────────────────────────────────┐   │   │
│  │     │  Segment (磁盘上独立的倒排索引文件)        │   │   │
│  │     │  • 此时文档可搜索! → 近实时 (NRT)         │   │   │
│  │     │  • Segment 不可变 (immutable)             │   │   │
│  │     │  • 每个 refresh 生成一个新 Segment        │   │   │
│  │     └───────────────────────────────────────────┘   │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
│  ┌─────────────────────────────────────────────────────┐   │
│  │                    定时 Flush (默认 30min 或 512MB)│   │
│  │                                                     │   │
│  │  6. 将所有 Segment fsync 到磁盘                        │   │
│  │     ┌───────────────────────────────────────────┐   │   │
│  │     │  • 执行 fsync(真正的磁盘持久化)          │   │   │
│  │     │  • 清空 Translog(数据已安全落盘)        │   │   │
│  │     │  • Commit Point 更新                      │   │   │
│  │     └───────────────────────────────────────────┘   │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
│  ┌─────────────────────────────────────────────────────┐   │
│  │                    后台 Merge                         │   │
│  │                                                     │   │
│  │  7. 合并多个小 Segment 为大 Segment                    │   │
│  │     • 减少文件句柄和搜索时的 Segment 遍历开销       │   │
│  │     • 删除标记为 deleted 的文档(物理删除)         │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64

3.2 Refresh 间隔:近实时搜索的代价 ​

┌─────────────────────────────────────────────────────────────┐
│                Refresh 间隔的权衡                             │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  默认 refresh_interval = 1s                                  │
│  → 文档写入后最多 1 秒即可被搜索到                           │
│  → 代价:每秒产生新的 Segment,后续需要频繁 Merge           │
│                                                             │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  场景                   推荐 refresh_interval        │   │
│  │  ───────────────────────────────────────────────     │   │
│  │  实时搜索(电商、新闻)   1s (默认)                  │   │
│  │  日志分析 (ELK)          30s - 60s                   │   │
│  │  批量导入数据中           -1 (禁用 refresh)           │   │
│  │  归档数据/只读索引        -1 (永远不需要 refresh)     │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
│  批量写入优化:                                             │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  PUT /my_index/_settings                              │   │
│  │  {                                                    │   │
│  │    "refresh_interval": "-1",     // 禁用              │   │
│  │    "number_of_replicas": 0       // 禁用副本          │   │
│  │  }                                                    │   │
│  │  // ... bulk 导入 ...                                 │   │
│  │  PUT /my_index/_settings                              │   │
│  │  {                                                    │   │
│  │    "refresh_interval": "1s",                           │   │
│  │    "number_of_replicas": 1                             │   │
│  │  }                                                    │   │
│  │  POST /my_index/_forcemerge?max_num_segments=1        │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

3.3 Translog:数据安全的最后防线 ​

┌─────────────────────────────────────────────────────────────┐
│                    Translog 机制详解                          │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  Translog 的两种持久化策略:                                │
│                                                             │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  request(默认):每次写入都 fsync translog           │   │
│  │    → 最安全,节点崩溃不丢数据                         │   │
│  │    → 写入性能受磁盘 fsync 频率限制                   │   │
│  │                                                      │   │
│  │  async:每隔 sync_interval 异步 fsync                │   │
│  │    → 写入吞吐更高(减少 fsync 次数)                  │   │
│  │    → 崩溃可能丢失 sync_interval 内的数据              │   │
│  │    → 配置:                                          │   │
│  │      "index.translog.durability": "async"            │   │
│  │      "index.translog.sync_interval": "5s"            │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
│  Translog 在崩溃恢复中的作用:                              │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  节点崩溃重启后:                                     │   │
│  │                                                      │   │
│  │  1. 读取最后一次 Flush 的 Commit Point               │   │
│  │  2. 重放 Translog 中 Commit Point 之后的所有操作     │   │
│  │  3. Replay 完成后,数据恢复到崩溃前状态              │   │
│  │                                                      │   │
│  │  Translog 的位置:                                    │   │
│  │  data/nodes/0/indices/<index_uuid>/0/translog/      │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

第4部分:集群健康 ​

4.1 Green / Yellow / Red ​

┌─────────────────────────────────────────────────────────────┐
│                    集群健康三色状态                           │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  GREEN(绿)                                          │   │
│  │  ┌──────────────────────────────────────────────┐   │   │
│  │  │  所有主分片和副本分片都已分配且可用            │   │   │
│  │  │  这是理想状态,一切正常                        │   │   │
│  │  └──────────────────────────────────────────────┘   │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  YELLOW(黄)                                         │   │
│  │  ┌──────────────────────────────────────────────┐   │   │
│  │  │  所有主分片已分配,但至少一个副本分片未分配     │   │   │
│  │  │  数据安全:主分片正常 → 写入正常、搜索正常     │   │   │
│  │  │  风险:主分片所在的节点挂掉 → 数据不可用       │   │   │
│  │  │                                              │   │   │
│  │  │  常见原因:                                    │   │   │
│  │  │  • 单节点集群(副本无法分配)                  │   │   │
│  │  │  • 节点数 < 副本数+1                           │   │   │
│  │  │  • 磁盘满了 (disk watermark)                   │   │   │
│  │  │  • 分片分配被手动禁用                          │   │   │
│  │  └──────────────────────────────────────────────┘   │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  RED(红)                                            │   │
│  │  ┌──────────────────────────────────────────────┐   │   │
│  │  │  至少一个主分片未分配                         │   │   │
│  │  │  数据安全:丢失数据或不可用                    │   │   │
│  │  │  影响:写入/搜索返回 503 / partial results     │   │   │
│  │  │                                              │   │   │
│  │  │  常见原因:                                    │   │   │
│  │  │  • 持有主分片的节点宕机且无副本                │   │   │
│  │  │  • 磁盘满了导致分片不可写入                    │   │   │
│  │  │  • 脑裂导致多主分片冲突                       │   │   │
│  │  └──────────────────────────────────────────────┘   │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

4.2 Unassigned Shards 排查流程 ​

┌─────────────────────────────────────────────────────────────┐
│              Unassigned Shards 排查五步法                     │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  Step 1: 查看未分配原因                                     │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  GET /_cat/shards?v&h=index,shard,prirep,state,     │   │
│  │      unassigned.reason                                │   │
│  │                                                      │   │
│  │  常见 reason:                                        │   │
│  │  • INDEX_CREATED: 索引刚创建,副本尚未分配            │   │
│  │  • CLUSTER_RECOVERED: 集群从 full restart 恢复       │   │
│  │  • ALLOCATION_FAILED: 分配失败(磁盘满等)           │   │
│  │  • NODE_LEFT: 节点离开,副本需要重新分配             │   │
│  │  • REALLOCATED: 分片正在重新分配中                    │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
│  Step 2: 查看分配解释                                      │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  GET /_cluster/allocation/explain                    │   │
│  │  {                                                  │   │
│  │    "index": "products",                             │   │
│  │    "shard": 0,                                      │   │
│  │    "primary": false                                 │   │
│  │  }                                                  │   │
│  │  → 返回详细的分配失败原因和决策过程                  │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
│  Step 3: 检查磁盘水位线                                    │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  cluster.routing.allocation.disk.watermark.low: 85% │   │
│  │    → 达到此值,不再分配新分片到该节点               │   │
│  │  cluster.routing.allocation.disk.watermark.high: 90%│   │
│  │    → 达到此值,尝试将分片迁移到其他节点              │   │
│  │  cluster.routing.allocation.disk.watermark.flood:   │   │
│  │    95% (固定)                                        │   │
│  │    → 达到此值,ES 将索引设为 read-only-allow-delete │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
│  Step 4: 手动重试分配                                      │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  POST /_cluster/reroute?retry_failed=true            │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
│  Step 5: 如果还不行,检查配置                              │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  • 是否禁用了 shard allocation?                      │   │
│  │    GET /_cluster/settings                            │   │
│  │    → cluster.routing.allocation.enable: "none"       │   │
│  │                                                      │   │
│  │  • 恢复:                                             │   │
│  │    PUT /_cluster/settings                            │   │
│  │    {"transient": {"cluster.routing.allocation.       │   │
│  │                   enable": "all"}}                     │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57

第5部分:集群运维 ​

5.1 滚动重启(Rolling Restart) ​

┌─────────────────────────────────────────────────────────────┐
│                    滚动重启操作流程                           │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  目标:升级 ES 版本或修改配置,服务不中断。                 │
│                                                             │
│  Step 1: 暂停分片分配(防止重启期间无意义的迁移)           │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  PUT /_cluster/settings                              │   │
│  │  {"transient": {"cluster.routing.allocation.         │   │
│  │                 enable": "none"}}                      │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
│  Step 2: 执行 sync flush(加速恢复)                        │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  POST /_flush/synced                                 │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
│  Step 3: 逐个重启节点                                      │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  For each node:                                      │   │
│  │    a) 停止 ES 进程                                   │   │
│  │    b) 执行升级/配置修改                              │   │
│  │    c) 启动 ES 进程                                    │   │
│  │    d) 等待节点重新加入集群                            │   │
│  │       GET /_cat/health?v  → 确认状态正常             │   │
│  │    e) 确认没有 unassigned shards                      │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
│  Step 4: 恢复分片分配                                      │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  PUT /_cluster/settings                              │   │
│  │  {"transient": {"cluster.routing.allocation.         │   │
│  │                 enable": "all"}}                       │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
│  Step 5: 等待集群恢复 Green 状态                           │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  GET /_cat/health?v                                  │   │
│  │  GET /_cat/recovery?v                                │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

5.2 快照备份与恢复 ​

┌─────────────────────────────────────────────────────────────┐
│                    快照备份策略                               │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  快照是 ES 唯一的全量备份方式,基于增量机制。               │
│                                                             │
│  Step 1: 注册快照仓库                                       │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  PUT /_snapshot/my_backup                            │   │
│  │  {                                                    │   │
│  │    "type": "fs",                                      │   │
│  │    "settings": {                                      │   │
│  │      "location": "/mnt/backups/es",                   │   │
│  │      "compress": true                                │   │
│  │    }                                                  │   │
│  │  }                                                    │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
│  Step 2: 创建快照                                          │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  PUT /_snapshot/my_backup/snapshot_2024_01_15        │   │
│  │  {                                                    │   │
│  │    "indices": "products,orders,logs-*",               │   │
│  │    "ignore_unavailable": true,                        │   │
│  │    "include_global_state": true                       │   │
│  │  }                                                    │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
│  Step 3: 监控快照进度                                      │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  GET /_snapshot/my_backup/snapshot_2024_01_15        │   │
│  │  GET /_snapshot/my_backup/_status                    │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
│  Step 4: 恢复快照                                         │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  POST /_snapshot/my_backup/snapshot_2024_01_15/      │   │
│  │       _restore                                        │   │
│  │  {                                                    │   │
│  │    "indices": "products",                             │   │
│  │    "rename_pattern": "products",                      │   │
│  │    "rename_replacement": "products_restored"          │   │
│  │  }                                                    │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
│  SLM (Snapshot Lifecycle Management) 自动备份策略:        │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  每天凌晨 2 点 → 增量快照                             │   │
│  │  每周日凌晨 3 点 → 全量快照                          │   │
│  │  保留策略:最近 7 天 + 最近 4 周 + 最近 3 月         │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

5.3 跨集群复制 (CCR) ​

┌─────────────────────────────────────────────────────────────┐
│                    跨集群复制 CCR                            │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  CCR 是 ES 白金版功能,用于跨数据中心的数据同步。           │
│                                                             │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  机房 A(主集群)        机房 B(从集群)             │   │
│  │  ┌──────────────┐      ┌──────────────┐             │   │
│  │  │  Node 1-3    │      │  Node 1-3    │             │   │
│  │  │  (Leader)    │ ───→ │  (Follower)  │             │   │
│  │  └──────────────┘      └──────────────┘             │   │
│  │        │                      │                      │   │
│  │   写入正常                只读(或故障切换后可写)    │   │
│  │                                                      │   │
│  │  同步方式:基于 Translog 的增量复制                  │   │
│  │  延迟:秒级(网络延迟 + 写入延迟)                   │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
│  使用场景:                                                 │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  • 灾备:主集群宕机后切到从集群                       │   │
│  │  • 就近搜索:中国用户 → 中国集群,美国用户 → 美国集群│   │
│  │  • 数据聚合:多个集群的数据同步到一个中心集群         │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
│  配置 Follower Index:                                      │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  PUT /products/_ccr/follow                           │   │
│  │  {                                                    │   │
│  │    "remote_cluster": "cluster_beijing",               │   │
│  │    "leader_index": "products"                        │   │
│  │  }                                                    │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

第6部分:性能调优 ​

6.1 Heap 与内存管理 ​

┌─────────────────────────────────────────────────────────────┐
│                    Heap 内存配置                              │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  ES 是基于 JVM 的,Heap 配置是最关键的性能参数。           │
│                                                             │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  32GB 诅咒:                                         │   │
│  │  ┌──────────────────────────────────────────────┐   │   │
│  │  │  JVM 在使用超过 32GB heap 时,对象指针从        │   │   │
│  │  │  32-bit 压缩指针变为 64-bit 普通指针            │   │   │
│  │  │  → 每个对象增加约 50% 的内存占用                │   │   │
│  │  │  → 等效于花了更多内存却没什么性能收益            │   │   │
│  │  │                                              │   │   │
│  │  │  所以 Heap 建议:不超过 30.5GB (31GB)          │   │   │
│  │  │  官方推荐: 50% 物理内存,但最大 31GB            │   │   │
│  │  └──────────────────────────────────────────────┘   │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
│  Heap 分配策略:                                            │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  剩余 50% 内存给 OS Page Cache (Lucene 使用)        │   │
│  │  ┌──────────────────────────────────────────────┐   │   │
│  │  │  总内存 64GB 的机器:                          │   │   │
│  │  │  ┌──────────────────────────────────────┐     │   │
│  │  │  │  Heap: 31GB  (JVM)                   │     │   │
│  │  │  │  ├─ young gen: ~3GB                  │     │   │
│  │  │  │  └─ old gen:   ~28GB                 │     │   │
│  │  │  ├──────────────────────────────────────┤     │   │
│  │  │  │  OS Page Cache: ~31GB (给 Lucene)    │     │   │
│  │  │  ├──────────────────────────────────────┤     │   │
│  │  │  │  OS + 其他进程: ~2GB                 │     │   │
│  │  │  └──────────────────────────────────────┘     │   │
│  │  └──────────────────────────────────────────────┘   │   │
│  │                                                      │   │
│  │  为什么 OS Page Cache 如此重要?                     │   │
│  │  • Lucene 的 Segment 文件存在磁盘上                  │   │
│  │  • OS Page Cache 将这些文件缓存到内存                │   │
│  │  • 命中 Page Cache 的查询比命中磁盘快 100+ 倍       │   │
│  │  • 如果 Heap 太大,挤占了 Page Cache,反而更慢      │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

6.2 Bulk 写入优化 ​

┌─────────────────────────────────────────────────────────────┐
│                    Bulk 写入优化参数                          │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  Bulk API 是 ES 写入的唯一高性能方式。单个 doc 索引请求     │
│  意味着每次都是一次完整的网络往返 + refresh + translog     │
│                                                             │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  优化维度               推荐值         说明          │   │
│  │  ─────────────────────────────────────────────       │   │
│  │  bulk size              5-15MB         太小→网络    │   │
│  │                                        太大→OOM     │   │
│  │  bulk 条数              500-2000       配合size使用 │   │
│  │  concurrent requests    2-4 per node   不是越大越好 │   │
│  │  refresh_interval       -1 (导入中)    导入完恢复   │   │
│  │  number_of_replicas     0 (导入中)     导入完补副本 │   │
│  │  translog durability    async (可选)   牺牲安全换    │   │
│  │                                       吞吐          │   │
│  │  index buffer size      10-20% heap   越大→越少    │   │
│  │                                       refresh       │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
│  Bulk 大小测试方法:                                        │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  从 1MB 开始 → 逐步增大到 20MB                       │   │
│  │  观察指标:写入 TPS、GC 频率、请求超时率             │   │
│  │  找到 TPS 不再增长但 GC 开始增加的那个拐点           │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

6.3 查询缓存全景 ​

┌─────────────────────────────────────────────────────────────┐
│                    ES 查询缓存体系                            │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  ES 有四层缓存,从快到慢依次是:                            │
│                                                             │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  1. Request Cache (Shard 级别)                       │   │
│  │     ┌───────────────────────────────────────────┐   │   │
│  │     │  条件:size=0 的查询(即只查聚合)         │   │   │
│  │     │  缓存:整个查询的 JSON 结果                │   │   │
│  │     │  命中条件:完全相同的 JSON 请求体          │   │   │
│  │     │  失效:shard refresh 后自动失效            │   │   │
│  │     │  监控:GET /_stats/request_cache           │   │   │
│  │     └───────────────────────────────────────────┘   │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  2. Query Cache (Node 级别)                          │   │
│  │     ┌───────────────────────────────────────────┐   │   │
│  │     │  条件:filter context 的查询               │   │   │
│  │     │  缓存:filter 匹配的文档 ID 集合 (BitSet)  │   │   │
│  │     │  命中条件:完全相同的 filter 条件           │   │   │
│  │     │  大小:默认 10% heap,LRU 淘汰             │   │   │
│  │     │  监控:GET /_stats/query_cache             │   │   │
│  │     └───────────────────────────────────────────┘   │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  3. Field Data Cache (Node 级别)                     │   │
│  │     ┌───────────────────────────────────────────┐   │   │
│  │     │  用途:排序、聚合、script 用的字段数据     │   │   │
│  │     │  针对:text 字段的 fielddata(默认禁用)   │   │   │
│  │     │         keyword/numeric 的 doc_values       │   │   │
│  │     │  大小:默认 40% heap (但尽量别让聚合吃满)   │   │   │
│  │     │  注意:fielddata 是堆内,doc_values 是堆外  │   │   │
│  │     └───────────────────────────────────────────┘   │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  4. OS Page Cache (OS 级别,最重要的缓存)           │   │
│  │     ┌───────────────────────────────────────────┐   │   │
│  │     │  缓存:Lucene Segment 文件的磁盘页         │   │   │
│  │     │  优点:不需要 JVM Heap,利用 OS 内存管理   │   │   │
│  │     │  监控:无法直接查看,通过 disk IO 间接判断 │   │   │
│  │     │         (iostat, node_stats 的 disk 指标)   │   │   │
│  │     └───────────────────────────────────────────┘   │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
│  缓存监控关键指标:                                         │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  GET /_nodes/stats/indices/query_cache,             │   │
│  │      request_cache,fielddata,segments?human         │   │
│  │                                                      │   │
│  │  关注:                                               │   │
│  │  • query_cache.hit_count / miss_count                │   │
│  │  • fielddata.evictions(驱逐过多说明内存不够)       │   │
│  │  • segments.memory_in_bytes(Segment 内存占用)     │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61

核心总结 ​

总结1:节点角色 ​

Master  → 集群管理(创建索引、分配分片、节点管理)
Data    → 数据存储 + 搜索执行(CPU/IO 密集)
Ingest  → 写入预处理(Pipeline 处理)
Coordinating → 请求路由 + 结果合并(负载均衡)
1
2
3
4

总结2:写入链路 ​

文档 → Coordinating Node → Primary Shard
  → Translog (WAL) → In-Memory Buffer
    → Refresh (1s) → Segment (可搜索, NRT)
      → Flush (30min) → fsync + 清 Translog
        → Merge → 合并小 Segment
1
2
3
4
5

总结3:集群健康 ​

Green  → 所有主+副本已分配
Yellow → 主分片正常,部分副本未分配(数据安全但高可用受损)
Red    → 有主分片未分配(数据可能丢失)
1
2
3

总结4:性能调优关键参数 ​

Heap: 31GB 上限(32GB 压缩指针诅咒)
OS Page Cache: 至少占物理内存的 50%
Bulk: 5-15MB batch, 2-4 并发
Refresh: 根据场景调整(批量导入时设为 -1)
副本: 批量导入时设为 0,导入完后补副本
1
2
3
4
5

章节测试 ​

测试1:节点角色 ​

如果集群有 3 个节点,全部配置为 master: true, data: true,当其中 1 个节点宕机时会发生什么?

测试2:分片计算 ​

100GB 的数据,3 个数据节点(每节点 4 核 32GB RAM),应该设置多少个主分片?

测试3:写入流程 ​

新写入的文档为什么不能立即被搜索到?ES 是如何做到"近实时"搜索的?

测试4:集群健康 ​

Yellow 状态意味着什么?在单节点集群中,这是正常的吗?

测试5:内存 ​

为什么 ES 的 heap 不建议超过 31GB?OS Page Cache 的作用是什么?

测试6:备份 ​

你需要设计一个灾备方案:主集群在北京,希望在上海有一个热备份集群。应该用什么方案?

测试7:综合故障 ​

凌晨 3 点,集群变 Red。你是值班人员。描述完整的排查和处理流程。


参考答案 ​

测试1答案 ​

答案:剩余 2 个节点会选举出新的 Master(因为 discovery.zen.minimum_master_nodes 或 cluster.initial_master_nodes 的设置),集群继续运行。但由于副本分片分布在剩余节点上,集群可能短暂 Yellow(副本迁到其他节点后恢复)。如果宕机节点持有主分片且无副本,则集群变 Red。


测试2答案 ​

答案:

  • 数据量约束:100GB / 30GB = 3-4 个
  • CPU 约束:3×4=12 核 × 2 = 24 个上限
  • Heap 约束:31GB × 20 = 620 个上限
  • 推荐:5-6 个主分片(预留增长空间,后续可扩展节点数)
  • 副本数:1(2 份拷贝,安全 + 可集群扩容)

测试3答案 ​

答案:新文档先写入 In-Memory Buffer,此时未构建倒排索引的 Segment 文件,所以不可搜索。每隔 1 秒(默认 refresh_interval),ES 将 Buffer 中的文档写入新的 Segment 文件并打开,文档变为可搜索。这就是"近实时"(Near Real-Time, NRT)——不是实时的,有最多 1 秒的延迟。


测试4答案 ​

答案:Yellow 表示所有主分片已分配,但至少一个副本分片未分配。在单节点集群中,这是正常的(副本无法分配到同一节点,违反高可用原则)。在生产多节点集群中,Yellow 通常需要排查(节点不足、磁盘满、分片迁移中等)。


测试5答案 ​

答案:因为 JVM 的压缩对象指针(Compressed OOPs)在 heap 超过 32GB 时失效,每个对象指针从 32-bit 变为 64-bit,内存占用增加约 50%。建议 heap 设 31GB 或更小。

OS Page Cache 缓存 Lucene 的 Segment 文件到内存,是 ES 最重要的缓存层。由于 Lucene 数据文件不可变,OS Page Cache 的命中率极高。如果 Heap 太大挤占了 Page Cache,反而导致大量磁盘 IO,查询性能断崖式下跌。


测试6答案 ​

答案:使用 CCR (Cross-Cluster Replication) + 上海集群作为 Follower 索引。北京集群正常写入,CCR 基于 Translog 将变更秒级同步到上海集群。故障切换时,将上海集群的 Follower 提升为常规索引,流量切过去。同时需要配置客户端(应用/网关层)的集群切换逻辑。


测试7答案 ​

答案:排查流程:

  1. 确认 Red 范围和影响面

    GET /_cat/health?v
    GET /_cat/indices?v&health=red
    1
    2
  2. 查看未分配分片及原因

    GET /_cat/shards?v&h=index,shard,prirep,state,unassigned.reason
    GET /_cluster/allocation/explain (针对 Red 的分片)
    1
    2
  3. 常见原因及处理:

    • 如果 reason=NODE_LEFT → 检查节点是否宕机,尝试重启
    • 如果磁盘水位过高 → 清理磁盘或扩容,然后 POST /_cluster/reroute?retry_failed
    • 如果多节点同时宕机 → 先恢复节点,若数据真丢了则从快照恢复
  4. 如果确认数据丢失且无副本:

    POST /_cluster/reroute?retry_failed=true  {放弃分配的命令}
    1

    或 DELETE 问题索引,从快照恢复

  5. 记录故障时间线、通知相关方、事后复盘


相关笔记 ​

  • [[./00-overview]] - 搜索引擎概览
  • [[./02-elasticsearch-queries]] - ES 查询 DSL 深入
  • [[/03-web/07-middleware/06-elasticsearch]] - ES 倒排索引深入

下一步学习 ​

  • [ ] 阅读 04 - Meilisearch 与替代方案

学习状态:🟡 开始学习

最后更新于:

Pager
上一篇3. Elasticsearch 查询 DSL 深入——为什么你的搜索总是不准 / Elasticsearch Query DSL Deep Dive
下一篇5. Meilisearch 与轻量搜索替代方案——当 ES 太重时 / Meilisearch and Lightweight Search Alternatives

持续记录,持续成长

Copyright © Tidenflow