Elasticsearch 操作手册
本文档面向 ES 6.8.x 生产运维场景,涵盖集群部署、API 操作、故障排查、性能优化与数据迁移。命令示例保留现场 IP/账号占位,使用前请替换为实际环境。
目录
- [什么是 Elasticsearch](#什么是 Elasticsearch)
- [ES 工作原理与核心架构](#ES 工作原理与核心架构)
- 核心概念与存储原理
- [部署 ES 集群注意事项](#部署 ES 集群注意事项)
- [Search-Guard 安全加固](#Search-Guard 安全加固)
- [ES API 命令行操作手册](#ES API 命令行操作手册)
- [Elasticdump 导入导出](#Elasticdump 导入导出)
- 排错与集群状态分析
- 性能优化
- 分片迁移
什么是 Elasticsearch
Elasticsearch(ES)是一款基于 Apache Lucene 的分布式搜索与分析引擎,擅长:
- 全文检索:倒排索引 + BM25 等相关性评分
- 结构化查询与聚合:filter、aggregation、pipeline
- 近实时(Near Real-Time)分析 :写入后默认约 1s 可搜(受
refresh_interval影响) - 水平扩展:通过分片(Shard)把索引分布到多节点
与关系型数据库的对照理解:
| 关系型数据库 | Elasticsearch |
|---|---|
| Database | Index(索引) |
| Table | Type(6.x 仍有;7.x+ 已废弃) |
| Row | Document(JSON 文档) |
| Column | Field(字段) |
| Schema | Mapping(映射) |
| Index | 倒排索引 + 正排/doc values |
分布式特性 :文档按 _routing(默认 _id)哈希路由到某个主分片(Primary);副本分片(Replica)是主分片的只读拷贝,用于读扩展与故障切换。任意节点均可接收 REST 请求,协调节点负责将请求转发到持有目标分片的节点。
集群发现(6.x) :节点自动发现与 Master 选举基于 Zen Discovery (7.x 起逐步演进为 Cluster Coordination )。节点间通过类 Gossip 机制交换集群状态,Master 节点负责维护 Cluster State(索引元数据、分片路由表、节点列表等),不直接参与数据读写(除非该节点同时是 Data 节点)。
ES 工作原理与核心架构
整体架构
#mermaid-svg-oTjmX2BVxnjXjNy6{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-oTjmX2BVxnjXjNy6 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-oTjmX2BVxnjXjNy6 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-oTjmX2BVxnjXjNy6 .error-icon{fill:#552222;}#mermaid-svg-oTjmX2BVxnjXjNy6 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-oTjmX2BVxnjXjNy6 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-oTjmX2BVxnjXjNy6 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-oTjmX2BVxnjXjNy6 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-oTjmX2BVxnjXjNy6 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-oTjmX2BVxnjXjNy6 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-oTjmX2BVxnjXjNy6 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-oTjmX2BVxnjXjNy6 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-oTjmX2BVxnjXjNy6 .marker.cross{stroke:#333333;}#mermaid-svg-oTjmX2BVxnjXjNy6 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-oTjmX2BVxnjXjNy6 p{margin:0;}#mermaid-svg-oTjmX2BVxnjXjNy6 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-oTjmX2BVxnjXjNy6 .cluster-label text{fill:#333;}#mermaid-svg-oTjmX2BVxnjXjNy6 .cluster-label span{color:#333;}#mermaid-svg-oTjmX2BVxnjXjNy6 .cluster-label span p{background-color:transparent;}#mermaid-svg-oTjmX2BVxnjXjNy6 .label text,#mermaid-svg-oTjmX2BVxnjXjNy6 span{fill:#333;color:#333;}#mermaid-svg-oTjmX2BVxnjXjNy6 .node rect,#mermaid-svg-oTjmX2BVxnjXjNy6 .node circle,#mermaid-svg-oTjmX2BVxnjXjNy6 .node ellipse,#mermaid-svg-oTjmX2BVxnjXjNy6 .node polygon,#mermaid-svg-oTjmX2BVxnjXjNy6 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-oTjmX2BVxnjXjNy6 .rough-node .label text,#mermaid-svg-oTjmX2BVxnjXjNy6 .node .label text,#mermaid-svg-oTjmX2BVxnjXjNy6 .image-shape .label,#mermaid-svg-oTjmX2BVxnjXjNy6 .icon-shape .label{text-anchor:middle;}#mermaid-svg-oTjmX2BVxnjXjNy6 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-oTjmX2BVxnjXjNy6 .rough-node .label,#mermaid-svg-oTjmX2BVxnjXjNy6 .node .label,#mermaid-svg-oTjmX2BVxnjXjNy6 .image-shape .label,#mermaid-svg-oTjmX2BVxnjXjNy6 .icon-shape .label{text-align:center;}#mermaid-svg-oTjmX2BVxnjXjNy6 .node.clickable{cursor:pointer;}#mermaid-svg-oTjmX2BVxnjXjNy6 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-oTjmX2BVxnjXjNy6 .arrowheadPath{fill:#333333;}#mermaid-svg-oTjmX2BVxnjXjNy6 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-oTjmX2BVxnjXjNy6 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-oTjmX2BVxnjXjNy6 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-oTjmX2BVxnjXjNy6 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-oTjmX2BVxnjXjNy6 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-oTjmX2BVxnjXjNy6 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-oTjmX2BVxnjXjNy6 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-oTjmX2BVxnjXjNy6 .cluster text{fill:#333;}#mermaid-svg-oTjmX2BVxnjXjNy6 .cluster span{color:#333;}#mermaid-svg-oTjmX2BVxnjXjNy6 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-oTjmX2BVxnjXjNy6 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-oTjmX2BVxnjXjNy6 rect.text{fill:none;stroke-width:0;}#mermaid-svg-oTjmX2BVxnjXjNy6 .icon-shape,#mermaid-svg-oTjmX2BVxnjXjNy6 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-oTjmX2BVxnjXjNy6 .icon-shape p,#mermaid-svg-oTjmX2BVxnjXjNy6 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-oTjmX2BVxnjXjNy6 .icon-shape .label rect,#mermaid-svg-oTjmX2BVxnjXjNy6 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-oTjmX2BVxnjXjNy6 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-oTjmX2BVxnjXjNy6 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-oTjmX2BVxnjXjNy6 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Elasticsearch 集群
客户端
分片分配决策
分片分配决策
副本同步
应用 / curl / Kibana
协调节点
接收请求、聚合结果
Master 节点
集群状态、分片分配
Data 节点 1
Primary / Replica
Data 节点 2
Primary / Replica
写入流程(Indexing)
理解写入路径是排查 write reject、yellow、recovery 慢 的基础。
副本分片节点 主分片节点 协调节点 客户端 副本分片节点 主分片节点 协调节点 客户端 #mermaid-svg-52HoIkS3uOUqHYbW{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-52HoIkS3uOUqHYbW .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-52HoIkS3uOUqHYbW .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-52HoIkS3uOUqHYbW .error-icon{fill:#552222;}#mermaid-svg-52HoIkS3uOUqHYbW .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-52HoIkS3uOUqHYbW .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-52HoIkS3uOUqHYbW .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-52HoIkS3uOUqHYbW .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-52HoIkS3uOUqHYbW .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-52HoIkS3uOUqHYbW .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-52HoIkS3uOUqHYbW .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-52HoIkS3uOUqHYbW .marker{fill:#333333;stroke:#333333;}#mermaid-svg-52HoIkS3uOUqHYbW .marker.cross{stroke:#333333;}#mermaid-svg-52HoIkS3uOUqHYbW svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-52HoIkS3uOUqHYbW p{margin:0;}#mermaid-svg-52HoIkS3uOUqHYbW .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-52HoIkS3uOUqHYbW text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-52HoIkS3uOUqHYbW .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-52HoIkS3uOUqHYbW .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-52HoIkS3uOUqHYbW .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-52HoIkS3uOUqHYbW .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-52HoIkS3uOUqHYbW #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-52HoIkS3uOUqHYbW .sequenceNumber{fill:white;}#mermaid-svg-52HoIkS3uOUqHYbW #sequencenumber{fill:#333;}#mermaid-svg-52HoIkS3uOUqHYbW #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-52HoIkS3uOUqHYbW .messageText{fill:#333;stroke:none;}#mermaid-svg-52HoIkS3uOUqHYbW .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-52HoIkS3uOUqHYbW .labelText,#mermaid-svg-52HoIkS3uOUqHYbW .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-52HoIkS3uOUqHYbW .loopText,#mermaid-svg-52HoIkS3uOUqHYbW .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-52HoIkS3uOUqHYbW .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-52HoIkS3uOUqHYbW .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-52HoIkS3uOUqHYbW .noteText,#mermaid-svg-52HoIkS3uOUqHYbW .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-52HoIkS3uOUqHYbW .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-52HoIkS3uOUqHYbW .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-52HoIkS3uOUqHYbW .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-52HoIkS3uOUqHYbW .actorPopupMenu{position:absolute;}#mermaid-svg-52HoIkS3uOUqHYbW .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-52HoIkS3uOUqHYbW .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-52HoIkS3uOUqHYbW .actor-man circle,#mermaid-svg-52HoIkS3uOUqHYbW line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-52HoIkS3uOUqHYbW :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} refresh(默认 1s)→ 新 segment 可搜索 flush(translog 阈值/定时)→ commit 落盘 POST /index/_doc(文档 JSON) 路由计算 shard = hash(_routing) % num_primary 转发到主分片 解析 mapping、分词、写 Lucene 内存缓冲 写 Translog(事务日志,防宕机丢数据) 并行复制到各副本 副本确认 写入成功 返回 _id / _version / result
关键步骤说明:
- 路由(Routing) :默认
shard_num = hash(_id) % number_of_primary_shards。同一_id始终落在同一主分片,保证更新/删除一致性。 - Analysis(分析) :文本字段经 Analyzer(Character Filter → Tokenizer → Token Filter)产生 Term ,写入倒排索引;数值/日期等走 doc values(列式存储,利于排序与聚合)。
- Translog:每次 index/delete 先记 translog,再响应客户端。节点崩溃重启时,用 translog 重放未 flush 的操作。
- Refresh :将内存 buffer 变为新 Segment 并打开搜索器,使文档近实时可见;频繁 refresh 会产生大量小 segment,触发 merge,影响写入性能。
- Flush :将 segment commit 到磁盘,并清理 translog;对应 Lucene 的
commit。
搜索流程(Search)
分片 1 分片 0 协调节点 客户端 分片 1 分片 0 协调节点 客户端 #mermaid-svg-MEas7gRVRWSd9Xr5{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-MEas7gRVRWSd9Xr5 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-MEas7gRVRWSd9Xr5 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-MEas7gRVRWSd9Xr5 .error-icon{fill:#552222;}#mermaid-svg-MEas7gRVRWSd9Xr5 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-MEas7gRVRWSd9Xr5 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-MEas7gRVRWSd9Xr5 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-MEas7gRVRWSd9Xr5 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-MEas7gRVRWSd9Xr5 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-MEas7gRVRWSd9Xr5 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-MEas7gRVRWSd9Xr5 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-MEas7gRVRWSd9Xr5 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-MEas7gRVRWSd9Xr5 .marker.cross{stroke:#333333;}#mermaid-svg-MEas7gRVRWSd9Xr5 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-MEas7gRVRWSd9Xr5 p{margin:0;}#mermaid-svg-MEas7gRVRWSd9Xr5 .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-MEas7gRVRWSd9Xr5 text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-MEas7gRVRWSd9Xr5 .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-MEas7gRVRWSd9Xr5 .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-MEas7gRVRWSd9Xr5 .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-MEas7gRVRWSd9Xr5 .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-MEas7gRVRWSd9Xr5 #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-MEas7gRVRWSd9Xr5 .sequenceNumber{fill:white;}#mermaid-svg-MEas7gRVRWSd9Xr5 #sequencenumber{fill:#333;}#mermaid-svg-MEas7gRVRWSd9Xr5 #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-MEas7gRVRWSd9Xr5 .messageText{fill:#333;stroke:none;}#mermaid-svg-MEas7gRVRWSd9Xr5 .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-MEas7gRVRWSd9Xr5 .labelText,#mermaid-svg-MEas7gRVRWSd9Xr5 .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-MEas7gRVRWSd9Xr5 .loopText,#mermaid-svg-MEas7gRVRWSd9Xr5 .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-MEas7gRVRWSd9Xr5 .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-MEas7gRVRWSd9Xr5 .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-MEas7gRVRWSd9Xr5 .noteText,#mermaid-svg-MEas7gRVRWSd9Xr5 .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-MEas7gRVRWSd9Xr5 .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-MEas7gRVRWSd9Xr5 .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-MEas7gRVRWSd9Xr5 .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-MEas7gRVRWSd9Xr5 .actorPopupMenu{position:absolute;}#mermaid-svg-MEas7gRVRWSd9Xr5 .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-MEas7gRVRWSd9Xr5 .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-MEas7gRVRWSd9Xr5 .actor-man circle,#mermaid-svg-MEas7gRVRWSd9Xr5 line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-MEas7gRVRWSd9Xr5 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} par Query Phase par Fetch Phase GET /index/_search 解析 query,确定涉及哪些分片 查询 + 取 topN doc id + score 查询 + 取 topN doc id + score 合并各分片结果,全局排序 按 doc id 取 _source 按 doc id 取 _source 返回 hits
Query Then Fetch 两阶段:
- Query 阶段 :各分片本地检索,返回匹配的
doc_id +_score`(或 sort values),协调节点合并为全局 TopN。 - Fetch 阶段 :协调节点向相关分片请求完整
_source(或指定stored_fields)。
因此:分片越多,单次查询需要 fan-out 的分片越多,协调开销越大(Over-sharding 问题)。
倒排索引原理(Lucene Segment)
每个分片底层是一个 Lucene Index,由多个 Segment(不可变)组成:
文档: "Elasticsearch 很快"
分词: [elasticsearch] [很快]
倒排表:
elasticsearch → [doc1, doc5, doc9]
很快 → [doc1, doc3]
- 写入:新文档进入新 segment(append-only),旧 segment 不原地修改。
- 删除 :打 delete mark,空间不立即回收。
- 更新:旧 doc 标记删除 + 新 doc 写入新 segment(逻辑更新 = 删 + 写)。
- Merge :后台合并小 segment 为大 segment,回收删除空间;
_forcemerge可手动触发。
分片与副本机制
| 概念 | 说明 |
|---|---|
| Primary Shard | 索引数据的唯一写入入口;创建索引时主分片数不可变 |
| Replica Shard | 主分片的拷贝;可提升读吞吐、参与搜索;主分片丢失时可**提升(promote)**为新主 |
| 分配约束 | 同一索引的主分片与副本不能在同一节点 |
| 副本数公式 | 最大副本数受节点数限制:replicas + 1 ≤ 数据节点数 |
集群健康与分片关系:
- Green:所有主分片 + 副本分片均已 STARTED
- Yellow :所有主分片已分配,部分副本未分配(常见:节点不足、磁盘水位、分配策略限制)
- Red :部分主分片未分配 → 对应索引部分/全部数据不可读写
核心概念与存储原理
节点角色(6.x 典型划分)
| 角色 | 配置 | 职责 |
|---|---|---|
| Master-eligible | node.master: true |
参与 Master 选举,维护 Cluster State |
| Data | node.data: true |
存储分片,执行索引/搜索 |
| Ingest | node.ingest: true |
执行 ingest pipeline 预处理 |
| Coordinating only | 上述均为 false | 仅转发请求,减轻 Data 节点 HTTP 压力 |
生产建议:专用 Master 节点(3 个) + Data 节点 + 可选 Coordinating 节点,避免 Master 节点因 GC 或负载过高导致集群状态更新阻塞。
磁盘水位与只读保护
ES 内置磁盘使用率保护(默认):
| 阈值 | 默认 | 行为 |
|---|---|---|
| flood stage | 95% | 索引块写入,可能触发 read_only_allow_delete |
| high watermark | 90% | 禁止向该节点新分配分片 |
| low watermark | 85% | 尝试将分片迁离该节点 |
这就是为什么磁盘满后会出现 cluster_block_exception: read-only / allow delete,需要用 _settings 解除(见排错)。
Near Real-Time 与持久性权衡
| 配置 | 作用 | 性能 vs 可靠性 |
|---|---|---|
refresh_interval |
刷新间隔,默认 1s |
调大 → 写入更快,搜索延迟增大 |
index.translog.durability |
request(每次写刷盘)/ async |
async → 写入更快,可能丢最近几秒数据 |
index.translog.sync_interval |
async 模式下刷盘间隔 | 与上配合使用 |
以上参数在写性能优化章节有具体调优示例。
部署es集群注意事项
生产部署前需调整 Linux 内核与进程限制,否则 ES 可能因 文件描述符不足 、mmap 区域不够 或 内存锁定失败 而无法启动或频繁 OOM。
原理说明
| 参数 | 原因 |
|---|---|
nofile 65536 |
每个分片、每个连接、每个 segment 文件都占用 fd;默认 1024 极易耗尽 |
memlock unlimited |
ES 建议 bootstrap.memory_lock: true,将 JVM heap 锁定在物理内存,避免 swap 导致 GC 停顿暴增 |
vm.max_map_count=655360 |
Lucene 通过 mmap 映射大量 segment 文件;低于 65530 时 ES 启动会报错 |
nproc |
限制单用户进程数;ES 多线程 + 插件可能触发默认限制 |
yaml
1、修改文件限制
vi /etc/security/limits.conf
* hard nofile 65536
* soft nproc 2048
* hard nproc 4096
* soft memlock unlimited
* hard memlock unlimited
2、调整进程数
vi /etc/security/limits.d/20-nproc.conf
* soft nproc 4096
root soft nproc unlimited
3、调整虚拟机内存&&最大连接数
vi /etc/sysctl.conf
vm.max_map_count=655360
fs.file-max=655360
sysctl -p
es安装并使用search-guard插件加固安全
直白的讲就是给 ES 添加 TLS 传输加密 + 身份认证 + 基于角色的访问控制(RBAC)。
Search-Guard 工作原理
#mermaid-svg-t5Vj0KNIqdGD8ldu{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-t5Vj0KNIqdGD8ldu .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-t5Vj0KNIqdGD8ldu .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-t5Vj0KNIqdGD8ldu .error-icon{fill:#552222;}#mermaid-svg-t5Vj0KNIqdGD8ldu .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-t5Vj0KNIqdGD8ldu .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-t5Vj0KNIqdGD8ldu .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-t5Vj0KNIqdGD8ldu .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-t5Vj0KNIqdGD8ldu .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-t5Vj0KNIqdGD8ldu .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-t5Vj0KNIqdGD8ldu .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-t5Vj0KNIqdGD8ldu .marker{fill:#333333;stroke:#333333;}#mermaid-svg-t5Vj0KNIqdGD8ldu .marker.cross{stroke:#333333;}#mermaid-svg-t5Vj0KNIqdGD8ldu svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-t5Vj0KNIqdGD8ldu p{margin:0;}#mermaid-svg-t5Vj0KNIqdGD8ldu .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-t5Vj0KNIqdGD8ldu .cluster-label text{fill:#333;}#mermaid-svg-t5Vj0KNIqdGD8ldu .cluster-label span{color:#333;}#mermaid-svg-t5Vj0KNIqdGD8ldu .cluster-label span p{background-color:transparent;}#mermaid-svg-t5Vj0KNIqdGD8ldu .label text,#mermaid-svg-t5Vj0KNIqdGD8ldu span{fill:#333;color:#333;}#mermaid-svg-t5Vj0KNIqdGD8ldu .node rect,#mermaid-svg-t5Vj0KNIqdGD8ldu .node circle,#mermaid-svg-t5Vj0KNIqdGD8ldu .node ellipse,#mermaid-svg-t5Vj0KNIqdGD8ldu .node polygon,#mermaid-svg-t5Vj0KNIqdGD8ldu .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-t5Vj0KNIqdGD8ldu .rough-node .label text,#mermaid-svg-t5Vj0KNIqdGD8ldu .node .label text,#mermaid-svg-t5Vj0KNIqdGD8ldu .image-shape .label,#mermaid-svg-t5Vj0KNIqdGD8ldu .icon-shape .label{text-anchor:middle;}#mermaid-svg-t5Vj0KNIqdGD8ldu .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-t5Vj0KNIqdGD8ldu .rough-node .label,#mermaid-svg-t5Vj0KNIqdGD8ldu .node .label,#mermaid-svg-t5Vj0KNIqdGD8ldu .image-shape .label,#mermaid-svg-t5Vj0KNIqdGD8ldu .icon-shape .label{text-align:center;}#mermaid-svg-t5Vj0KNIqdGD8ldu .node.clickable{cursor:pointer;}#mermaid-svg-t5Vj0KNIqdGD8ldu .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-t5Vj0KNIqdGD8ldu .arrowheadPath{fill:#333333;}#mermaid-svg-t5Vj0KNIqdGD8ldu .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-t5Vj0KNIqdGD8ldu .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-t5Vj0KNIqdGD8ldu .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-t5Vj0KNIqdGD8ldu .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-t5Vj0KNIqdGD8ldu .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-t5Vj0KNIqdGD8ldu .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-t5Vj0KNIqdGD8ldu .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-t5Vj0KNIqdGD8ldu .cluster text{fill:#333;}#mermaid-svg-t5Vj0KNIqdGD8ldu .cluster span{color:#333;}#mermaid-svg-t5Vj0KNIqdGD8ldu div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-t5Vj0KNIqdGD8ldu .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-t5Vj0KNIqdGD8ldu rect.text{fill:none;stroke-width:0;}#mermaid-svg-t5Vj0KNIqdGD8ldu .icon-shape,#mermaid-svg-t5Vj0KNIqdGD8ldu .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-t5Vj0KNIqdGD8ldu .icon-shape p,#mermaid-svg-t5Vj0KNIqdGD8ldu .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-t5Vj0KNIqdGD8ldu .icon-shape .label rect,#mermaid-svg-t5Vj0KNIqdGD8ldu .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-t5Vj0KNIqdGD8ldu .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-t5Vj0KNIqdGD8ldu .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-t5Vj0KNIqdGD8ldu :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} TLS 握手
通过
拒绝
客户端请求
HTTP/Transport
Search-Guard 拦截器
用户名密码 / 证书 DN 认证
sg_roles.yml 权限校验
Elasticsearch 核心
403 Forbidden
- Transport 层:节点间通信也走 TLS + 证书互信,防止内网嗅探。
- HTTP 层:REST API 需 Basic Auth 或客户端证书。
- sgadmin.sh :将
sgconfig/下 YAML 配置推送 到.sg*系统索引,集群内各节点读取生效。 - 注意 :
hash.sh生成的 bcrypt 密文每台机器独立 ,sg_internal_users.yml不可直接复制到其他节点后省略 hash 步骤。
yaml
1、安装city-elasticsearch-6.8.13-1.x86_64.rpm
2、下载search-guard插件(es版本和search-guard插件有对应版本 https://docs.search-guard.com/6.x-25/search-guard-versions)
wget https://releases.floragunn.com/search-guard-6/6.8.13-25.6/search-guard-6-6.8.13-25.6.zip
3、使用ES已有的插件工具,安装命令如下。会自动在ES的plugins目录下创建search-guard文件
/export/server/elasticsearch-6.8.13/bin/elasticsearch-plugin install -b file:///root/search-guard-6-6.8.13-25.6.zip
4、启动插件
cd /export/server/elasticsearch-6.8.13/plugins/search-guard-6/tools/
sh install_demo_configuration.sh (按提示,输入三次Y)
以上执行后,会自动给elasticsearch-6.8.3/config/elasticsearch.yml文件后面添加以下内容
searchguard.ssl.transport.pemcert_filepath: esnode.pem
searchguard.ssl.transport.pemkey_filepath: esnode-key.pem
searchguard.ssl.transport.pemtrustedcas_filepath: root-ca.pem
searchguard.ssl.transport.enforce_hostname_verification: false
searchguard.ssl.http.enabled: true
searchguard.ssl.http.pemcert_filepath: esnode.pem
searchguard.ssl.http.pemkey_filepath: esnode-key.pem
searchguard.ssl.http.pemtrustedcas_filepath: root-ca.pem
searchguard.allow_unsafe_democertificates: true
searchguard.allow_default_init_sgindex: true
searchguard.authcz.admin_dn:
- CN=kirk,OU=client,O=client,L=test, C=de
searchguard.audit.type: internal_elasticsearch
searchguard.enable_snapshot_restore_privilege: true
searchguard.check_snapshot_restore_write_privileges: true
searchguard.restapi.roles_enabled: ["sg_all_access"]
cluster.routing.allocation.disk.threshold_enabled: false
discovery.zen.minimum_master_nodes: 1
node.max_local_storage_nodes: 3
xpack.security.enabled: false
将上述生成的文件替换为以下几行即可
searchguard.ssl.transport.pemcert_filepath: es.pem
searchguard.ssl.transport.pemkey_filepath: es.key
searchguard.ssl.transport.pemtrustedcas_filepath: root-ca.pem
searchguard.ssl.transport.enforce_hostname_verification: false
searchguard.ssl.transport.resolve_hostname: false
xpack.security.enabled: false
searchguard.restapi.roles_enabled: ["sg_all_access"]
searchguard.authcz.admin_dn:
- CN=kirk.jdicity.local,OU=Ops,O=jdicity,DC=jdicity,DC=local
searchguard.cert.oid: 1.2.3.4.5.5
5、使用elasticsearch账户启动es 然后查看es索引时会提示需要输入密码 默认的账户密码是admin admin
6、修改es默认超管账户admin的密码方法
cd /export/server/elasticsearch-6.8.13/plugins/search-guard-6/tools/
sh hash.sh -p <新密码明文>
将上述得到的新密码密文串, 放入/export/server/elasticsearch-6.8.13/plugins/search-guard-6/sgconfig/sg_internal_users.yml文件,修改文件admin用户下的hash值(使用刚才得到的新密码密文串)
7、初始化Search-Guard。进入插件目录:/export/server/elasticsearch-6.8.13/plugins/search-guard-6/tools下执行
./sgadmin.sh -cd ../sgconfig -key ../../../config/kirk.key -cert ../../../config/kirk.pem -cacert ../../../config/root-ca.pem -nhnv -icl
Es-Api命令行操作手册
以下 API 基于 REST,可用 curl、Kibana Dev Tools 或任意 HTTP 客户端调用。带
-u user:pass表示 Search-Guard / X-Pack 认证。
yaml
elasticsearch相关知识补充点:
https://blog.csdn.net/weixin_43820556/category_11189819.html
1、es没密码时查看es节点方法
json
curl -XGET http://11.51.202.69:9200/_cat/nodes?v
master列是*的就是主节点
2、es有密码时查看节点方法
shell
[root@std40 config]# curl -XGET http://admin:j7fc03HZg3HB5NWa@192.168.30.13:9200/_cat/nodes?v
ip heap.percent ram.percent cpu load_1m load_5m load_15m node.role master name
192.168.30.15 56 79 1 0.34 0.21 0.12 mdi - 192.168.30.15
192.168.30.14 24 62 1 0.00 0.01 0.05 mdi - 192.168.30.14
192.168.30.13 48 99 0 0.34 0.15 0.08 mdi * 192.168.30.13
3、es查看安装了哪些插件的命令
shell
[root@std40 config]# curl -XGET http://admin:j7fc03HZg3HB5NWa@192.168.30.13:9200/_cat/plugins
192.168.30.15 search-guard-6 6.8.13-25.6
192.168.30.14 search-guard-6 6.8.13-25.6
192.168.30.13 search-guard-6 6.8.13-25.6
4、集群操作
查看集群健康状态
shell
[root@std40 config]# curl http://192.168.1.101:9200/_cat/health?v -uadmin:j7fc03HZg3HB5NWa
epoch timestamp cluster status node.total node.data shards pri relo init unassign pending_tasks max_task_wait_time active_shards_percent
1740470787 08:06:27 cityos green 3 3 82 75 0 0 0 0 - 100.0%
[root@std40 config]# curl http://ip:9200/_cluster/health
{
"cluster_name" : "my_cluster", 集群名称
"status" : "yellow", 集群健康值
"timed_out" : false, 是否超时
"number_of_nodes" : 3, 索引主分片数量
"number_of_data_nodes" : 3, 数据节点数量
"active_primary_shards" : 37, 活跃主分片数量
"active_shards" : 65, 活跃的分片数量
"relocating_shards" : 0, 迁移中的分片的数量
"initializing_shards" : 0, 初始化中的分片数量
"unassigned_shards" : 3, 未分配的分片数量
"delayed_unassigned_shards" : 0, 延迟未分配的分片数量
"number_of_pending_tasks" : 0, 尚未执行的集群级别更改的数量
"number_of_in_flight_fetch" : 0, 未完成的提取次数
"task_max_waiting_in_queue_millis" : 0, 自最早启动的任务等待执行以来的时间
"active_shards_percent_as_number" : 95.58823529411765 集群中活动分片的比率,以百分比表示
}
上面的api返回结果,如果存在大量number_of_pending_tasks,可以通过如下命令查看到底是哪些task卡住了 [root@std40 config]# curl -XGET http://ip:9200/_cat/pending_tasks?v
查看当前集群master
shell
[root@std40 config]# curl -XGET 'http://localhost:9200/_cat/master?v' -uadmin:xxxx
id host ip node
c3VlcKg4THmRPljFcp0fzQ 192.168.30.13 192.168.30.13 192.168.30.13
查看集群中每个节点上执行的任务
shell
# 查看节点上执行的task,执行开始时间,执行耗时等等
#?v:表示启用列标题(verbose mode),输出会显示列名。
#&detail:表示请求返回任务的详细信息,详细信息通常包括任务的运行时间、任务状态等。
#&s=start_time:表示结果按任务的开始时间(start_time)进行排序。
[root@std40 config]# curl -XGET "http://localhost:9200/_cat/tasks?v&detailed&s=start_time"
action task_id parent_task_id type start_time timestamp running_time ip node description
cluster:monitor/tasks/lists c3VlcKg4THmRPljFcp0fzQ:104932339 - transport 1740471126396 08:12:06 662.9micros 192.168.30.13 192.168.30.13
cluster:monitor/tasks/lists[n] c3VlcKg4THmRPljFcp0fzQ:104932340 c3VlcKg4THmRPljFcp0fzQ:104932339 direct 1740471126397 08:12:06 220.8micros 192.168.30.13 192.168.30.13
cluster:monitor/tasks/lists[n] H0dkLtkNRd2Y8ivFzXWDbw:1110007604 c3VlcKg4THmRPljFcp0fzQ:104932339 netty 1740471126397 08:12:06 258.8micros 192.168.30.14 192.168.30.14
cluster:monitor/tasks/lists[n] czX0QS8bQeC8B2k6UCrx6w:64357346 c3VlcKg4THmRPljFcp0fzQ:104932339 netty 1740471126397 08:12:06 325.7micros 192.168.30.15 192.168.30.15
# 查看task的详情
[root@std40 config]# curl -XGET 'http://localhost:9200/_tasks?detailed'
[root@std40 config]# curl -XGET 'http://localhost:9200/_tasks?detailed=true&actions=*/update/byquery'
查看每个节点的磁盘使用、shard分配情况
shell
#&s=disk.avail:asc:表示结果按磁盘可用空间 (disk.avail) 升序排序(asc),即从最少可用空间的节点开始显示
[root@std40 config]# curl -XGET "http://admin:j7fc03HZg3HB5NWa@192.168.30.13:9200/_cat/allocation?v&s=disk.avail:asc"
shards disk.indices disk.used disk.avail disk.total disk.percent host ip node
28 90.4gb 94.4gb 905gb 999.5gb 9 192.168.30.15 192.168.30.15 192.168.30.15
27 78.7gb 82gb 917.5gb 999.5gb 8 192.168.30.14 192.168.30.14 192.168.30.14
27 19.1gb 21.2gb 978.2gb 999.5gb 2 192.168.30.13 192.168.30.13 192.168.30.13
#字段说明:
shards:该节点上分配的分片数。
disk.indices:存储 Elasticsearch 索引数据的磁盘空间使用情况。
disk.used:已经使用的磁盘空间。
disk.avail:剩余的磁盘可用空间。
disk.total:总的磁盘空间。
disk.percent:已用磁盘空间的百分比。
host:节点的主机名。
ip:节点的 IP 地址。
node:节点名称。
查看节点热点线程情况
shell
[root@std40 config]# curl -XGET "http://admin:j7fc03HZg3HB5NWa@192.168.30.13:9200/_nodes/hot_threads"
::: {192.168.30.15}{czX0QS8bQeC8B2k6UCrx6w}{RxPmRg1QTZChI0dKM88iPA}{192.168.30.15}{192.168.30.15:9300}{ml.machine_memory=16646746112, ml.max_open_jobs=20, xpack.installed=true, ml.enabled=true}
Hot threads at 2025-02-25T08:20:04.208Z, interval=500ms, busiestThreads=3, ignoreIdleThreads=true:
::: {192.168.30.14}{H0dkLtkNRd2Y8ivFzXWDbw}{I6xZBpioSqW05XByKQKPzw}{192.168.30.14}{192.168.30.14:9300}{ml.machine_memory=16646746112, ml.max_open_jobs=20, xpack.installed=true, ml.enabled=true}
Hot threads at 2025-02-25T08:20:04.208Z, interval=500ms, busiestThreads=3, ignoreIdleThreads=true:
::: {192.168.30.13}{c3VlcKg4THmRPljFcp0fzQ}{ND8GDDgHSsagDTebWmCqZw}{192.168.30.13}{192.168.30.13:9300}{ml.machine_memory=16646746112, xpack.installed=true, ml.max_open_jobs=20, ml.enabled=true}
Hot threads at 2025-02-25T08:20:04.207Z, interval=500ms, busiestThreads=3, ignoreIdleThreads=true:
#解释说明:
#看到的这些信息并没有具体的线程栈信息,而只是报告了节点的热线程的总体状态
时间戳:报告的时间是 2025-02-25T08:20:04.208Z。
间隔:查询的时间间隔是 500 毫秒。
busiestThreads=3:这表示在该节点上监测到的最繁忙的线程数量是 3 个。
ignoreIdleThreads=true:表示忽略空闲线程,不报告空闲状态的线程。
kill集群中正在执行的任务
shell
#如果集群中存在长时间允许的任务,影响集群性能,可尝试将该任务取消
[root@std40 config]# curl -XPOST 'http://localhost:9200/_tasks/_cancel'
5、索引操作
查看es中的全部索引
shell
[root@std40 config]# curl "http://admin:j7fc03HZg3HB5NWa10.241.241.187:9200/_cat/indices?v" #查看全部索引
[root@std40 config]# curl -XGET "http://10.241.241.187:9200/_cat/indices?v&health=green" #查看状态为green的索引
[root@std40 config]# curl -XGET "http://10.241.241.187:9200/_cat/indices?v&health=yellow" #查看状态为yellow的索引
[root@std40 config]# curl -XGET "http://10.241.241.187:9200/_cat/indices?v&health=red" #查看状态为red的索引
查看es中的某个索引
shell
#注意:
# test是索引名
# ?size=10 指定返回的最大文档数为 10 条,可以根据需要调整这个数值。如果不设置 size 参数,它将默认返回 10 条数据
# pretty 参数可以格式化返回的 JSON 响应
[root@std40 config]# curl -XGET "http://l0.241.241.187:9200/test/_search?size=10&pretty"
#分页查看
# from=0:表示从第 0 条文档开始(即从头开始查询)。
# size=100:表示每次返回 100 条数据。
[root@std40 config]# curl -XGET "http://l0.241.241.187:9200/test/_search?from=0&size=100"
创建索引
shell
[root@std40 config]# curl -X PUT http://10.241.241.187:9200/test
删除索引
shell
[root@std40 config]# curl -X DELETE http://10.241.241.187:9200/test
删除单个索引中的某条数据
shell
#删除customer索引下类型为external的ID为2的数据
[root@std40 config]# curl -XDELETE http://10.241.241.187:9200/customer/external/2?pretty
解除索引只读状态
shell
#当es磁盘使用率超过85%时,es的状态会由读写状态转变为只读状态,导致es报错
[root@std40 config]# curl -XPUT 'http://es_ip:es_port/index_name/_settings' -H 'Content-Type: application/json' -d '{"index.blocks.read_only_allow_delete": false}' -uadmin:j7fc03HZg3HB5NWa
打开索引状态为close的索引
shell
[root@std40 config]# curl -X POST http://172.31.18.36:9200/索引名/_open?pretty -uicos:H466b7qB96iYc656G
关闭索引
shell
[root@std40 config]# curl -X POST http://172.31.18.36:9200/索引名/_close?pretty -uicos:H466b7qB96iYc656G
重命名索引,在这之前先创建dest索引
yaml
#确保创建的目标索引和源索引有一样的mapping结构。并提前备份源索引数据,避免数据丢失
[root@std40 config]# curl -H "Content-Type:application/json" -XPOST 'http://ip:9200/_reindex' -d '
{
"source": {
"index": "source_index"
},
"dest": {
"index": "dest_index"
}
}'
给test索引写入_doc类型数据
shell
[root@std40 config]# curl -s -H "Content-Type:application/json" -XPOST 'http://ip:9200/test/_doc' -d '{"name":"tom","age":32}'
计算集群/索引中的文档总数
shell
#整个集群的文档总数
[root@std40 config]# curl -XGET http://ip:9200/_cat/count?v
epoch timestamp count
1654148743 04:51:11 1314
#product索引中的文档总数
[root@std40 config]# curl -XGET http://ip:9200/_cat/count/product?v
epoch timestamp count
1654141931 03:52:11 13
#注意事项:
epoch:
这是一个 Unix 时间戳(自 1970 年 1 月 1 日以来的秒数)。在这个例子中,1740473315 是对应的时间戳,它转换成实际的时间是 2025年2月25日 08:48:35(UTC时间)。
timestamp:
这是查询返回的实际时间,以人类可读的格式显示。在这个例子中是 08:48:35,表示执行查询时的时间。这个时间和服务器的本机时间不一致的原因是时区差8小时
查看某个索引中的数据
shell
[root@std40 config]# curl -XGET 'http://localhost:9200/your_index_name/_search' -uadmin:xxxx
#命令执行后,会返回包含所有数据的JSON响应。
查看索引恢复情况
shell
#只显示特定索引(indexname)的活动恢复状态
[root@std40 config]# curl -XGET 'http://localhost:9200/_cat/recovery/indexname?v&active_only'
#显示所有活动恢复状态的分片,并自定义返回的列
[root@std40 config]# curl -XGET 'http://localhost:9200/_cat/recovery?v&active_only&h=index,shard,time,source_node,target_node,files_percent,bytes_percent,translog_ops_percent'
#参数说明:
v: 同样,v 参数使得输出包含表头,方便阅读。
active_only: 表示仅显示当前处于活动恢复状态的分片。
h=...: h 参数用来指定返回的字段。在这个命令中,指定了返回的列包括:
index: 索引名称
shard: 分片编号
time: 恢复耗时
source_node: 源节点(即恢复数据的来源节点)
target_node: 目标节点(即数据恢复到的目标节点)
files_percent: 文件恢复进度百分比
bytes_percent: 数据恢复进度百分比
translog_ops_percent: 恢复的事务日志操作百分比
查看索引的分片情况
shell
[root@std40 config]# curl -XGET "http://admin:j7fc03HZg3HB5NWa@192.168.30.13:9200/_cat/shards/graylog_306?v&s=shard:asc"
index shard prirep state docs store ip node
graylog_306 0 p STARTED 20000420 9.1gb 192.168.30.14 192.168.30.14
#参数含义
&s=shard:asc: 表示按 shard(分片编号)升序排序返回结果
#返回字段含义
index: 索引的名称。这里是 graylog_306,表示查询的是名为 graylog_306 的索引。
shard: 分片编号。这里是 0,表示查询的是该索引的第一个分片(索引分片从 0 开始编号)。
prirep: 表示分片是主分片(p)还是副本分片(r)。这里 p 表示这是主分片(Primary Shard)。
state: 分片的状态。这里是 STARTED,表示该分片已经启动并且正在运行。
docs: 该分片当前包含的文档数目。这里是 20000420,表示该分片中有 20,000,420 个文档。
store: 分片数据所占的磁盘空间大小。这里是 9.1gb,表示该分片的数据占用磁盘空间为 9.1 GB。
ip: 存储该分片的节点的 IP 地址。这里是 192.168.30.14,表示该分片位于该 IP 地址的节点上。
node: 存储该分片的节点的名称。这里是 192.168.30.14,表示该分片位于名为 192.168.30.14 的节点上。
加快索引分片恢复速度
shell
当节点间 rebalance 数据时、当节点发生重启时、当底层机器故障导致节点failover时,分片需要迁移数据或者重加载数据或者补数据,这时分片数据量如果太大,分片initing、reblance 过程会比较慢。es默认限制了并行恢复的数量、速度等。
可以修改如下配置加快 recovery 速度:
#查看正在进行的分片 recovery 进度
[root@std40 config]# curl -XGET http://localhost:9200/_recovery?detailed=true&active_only=true
#查看尚未分配的分片数量,其中:
"relocating_shards" 值为正在均衡的分片数量,
"initializing_shards" 值为正在初始化的分片数量,
"unassigned_shards" 值为尚未分配的分片数量
[root@std40 config]# curl -XGET http://localhost:9200/_cluster/health?pretty
{
"cluster_name": "test",
"status": "yellow",
"timed_out": false,
"number_of_nodes": 43,
"number_of_data_nodes": 32,
"active_primary_shards": 891,
"active_shards": 1708,
"relocating_shards": 5,
"initializing_shards": 17,
"unassigned_shards": 57,
"delayed_unassigned_shards": 0,
"number_of_pending_tasks": 0,
"number_of_in_flight_fetch": 0,
"task_max_waiting_in_queue_millis": 0,
"active_shards_percent_as_number": 0
}
#与分片恢复速度相关 4 个参数及默认值:
cluster.routing.allocation.cluster_concurrent_rebalance 该参数用来控制集群内同时运行的数据均衡任务个数,默认为值2
cluster.routing.allocation.node_initial_primaries_recoveries 该参数用来控制节点重启时,允许同时恢复几个主分片,默认值为2
cluster.routing.allocation.node_concurrent_recoveries 该参数用来控制节点除了主分片重启恢复以外其他情况下,允许同时运行的数据恢复任务,默认值为2
indices.recovery.max_bytes_per_sec 该参数用来控制节点恢复时的速率,默认值为40mb
#查看集群配置
[root@std40 config]# curl -XGET http://localhost:9200/_cluster/settings?pretty
{
"persistent" : {
"cluster" : {
"routing" : {
"allocation" : {
"enable" : "all"
}
}
}
},
"transient" : {
"cluster" : {
"routing" : {
"allocation" : {
"enable" : "all"
}
}
}
}
}
#注意:
可根据集群实际情况适当调大参数,参数调的越大,内部通信带宽占用会越大,集群读、写性能受影响会越大
#加快分片恢复的速度
[root@std40 config]# curl -XPUT http://localhost:9200/_cluster/settings
{
"transient" : {
"cluster.routing.allocation.node_concurrent_recoveries": 5,
"cluster.routing.allocation.cluster_concurrent_rebalance": 5,
"cluster.routing.allocation.node_initial_primaries_recoveries": 5,
"indices.recovery.max_bytes_per_sec": "1000mb"
}
}
#命令行
[root@std40 config]# curl -XPUT -H 'content-type: application/json' http://localhost:9200/_cluster/settings -d '
{
"transient" : {
"cluster.routing.allocation.node_concurrent_recoveries": 5,
"cluster.routing.allocation.cluster_concurrent_rebalance": 5,
"cluster.routing.allocation.node_initial_primaries_recoveries": 5,
"indices.recovery.max_bytes_per_sec": "1000mb"
}
}'
#恢复默认配置,2.x版本集群不支持 null,可使用 ""
[root@std40 config]# curl -XPUT http://localhost:9200/_cluster/settings
{
"transient" : {
"cluster.routing.allocation.node_concurrent_recoveries":null,
"cluster.routing.allocation.cluster_concurrent_rebalance":null,
"cluster.routing.allocation.node_initial_primaries_recoveries": null,
"indices.recovery.max_bytes_per_sec" : null
}
}
6、集群red/yellow原因分析
健康状态判定原理
集群 status 取所有索引中最差状态(Red > Yellow > Green)。判定逻辑:
#mermaid-svg-ADzoW0teoAcUtbs2{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-ADzoW0teoAcUtbs2 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-ADzoW0teoAcUtbs2 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-ADzoW0teoAcUtbs2 .error-icon{fill:#552222;}#mermaid-svg-ADzoW0teoAcUtbs2 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-ADzoW0teoAcUtbs2 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-ADzoW0teoAcUtbs2 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-ADzoW0teoAcUtbs2 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-ADzoW0teoAcUtbs2 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-ADzoW0teoAcUtbs2 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-ADzoW0teoAcUtbs2 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-ADzoW0teoAcUtbs2 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-ADzoW0teoAcUtbs2 .marker.cross{stroke:#333333;}#mermaid-svg-ADzoW0teoAcUtbs2 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-ADzoW0teoAcUtbs2 p{margin:0;}#mermaid-svg-ADzoW0teoAcUtbs2 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-ADzoW0teoAcUtbs2 .cluster-label text{fill:#333;}#mermaid-svg-ADzoW0teoAcUtbs2 .cluster-label span{color:#333;}#mermaid-svg-ADzoW0teoAcUtbs2 .cluster-label span p{background-color:transparent;}#mermaid-svg-ADzoW0teoAcUtbs2 .label text,#mermaid-svg-ADzoW0teoAcUtbs2 span{fill:#333;color:#333;}#mermaid-svg-ADzoW0teoAcUtbs2 .node rect,#mermaid-svg-ADzoW0teoAcUtbs2 .node circle,#mermaid-svg-ADzoW0teoAcUtbs2 .node ellipse,#mermaid-svg-ADzoW0teoAcUtbs2 .node polygon,#mermaid-svg-ADzoW0teoAcUtbs2 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-ADzoW0teoAcUtbs2 .rough-node .label text,#mermaid-svg-ADzoW0teoAcUtbs2 .node .label text,#mermaid-svg-ADzoW0teoAcUtbs2 .image-shape .label,#mermaid-svg-ADzoW0teoAcUtbs2 .icon-shape .label{text-anchor:middle;}#mermaid-svg-ADzoW0teoAcUtbs2 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-ADzoW0teoAcUtbs2 .rough-node .label,#mermaid-svg-ADzoW0teoAcUtbs2 .node .label,#mermaid-svg-ADzoW0teoAcUtbs2 .image-shape .label,#mermaid-svg-ADzoW0teoAcUtbs2 .icon-shape .label{text-align:center;}#mermaid-svg-ADzoW0teoAcUtbs2 .node.clickable{cursor:pointer;}#mermaid-svg-ADzoW0teoAcUtbs2 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-ADzoW0teoAcUtbs2 .arrowheadPath{fill:#333333;}#mermaid-svg-ADzoW0teoAcUtbs2 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-ADzoW0teoAcUtbs2 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-ADzoW0teoAcUtbs2 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ADzoW0teoAcUtbs2 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-ADzoW0teoAcUtbs2 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ADzoW0teoAcUtbs2 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-ADzoW0teoAcUtbs2 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-ADzoW0teoAcUtbs2 .cluster text{fill:#333;}#mermaid-svg-ADzoW0teoAcUtbs2 .cluster span{color:#333;}#mermaid-svg-ADzoW0teoAcUtbs2 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-ADzoW0teoAcUtbs2 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-ADzoW0teoAcUtbs2 rect.text{fill:none;stroke-width:0;}#mermaid-svg-ADzoW0teoAcUtbs2 .icon-shape,#mermaid-svg-ADzoW0teoAcUtbs2 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ADzoW0teoAcUtbs2 .icon-shape p,#mermaid-svg-ADzoW0teoAcUtbs2 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-ADzoW0teoAcUtbs2 .icon-shape .label rect,#mermaid-svg-ADzoW0teoAcUtbs2 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ADzoW0teoAcUtbs2 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-ADzoW0teoAcUtbs2 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-ADzoW0teoAcUtbs2 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 否
是
否
是
检查每个索引的每个分片
主分片已 STARTED?
索引 Red / 集群可能 Red
所有副本已 STARTED?
索引 Yellow / 集群可能 Yellow
索引 Green
_cluster/allocation/explain
常见原因
节点离线 / 不足
磁盘 > 85%/90%
副本数 > 节点可容纳
total_shards_per_node 限制
延迟分配 delayed_timeout
shell
集群状态red,有索引主分片未分配、node节点离线;
状态yellow,有索引副本分片未分配
用如下命令分析分片分片为什么没有被分配
[root@std40 config]# curl -XPOST http://localhost:9200/_cluster/allocation/explain
指定具体索引的分片分析其为什么不能改被分配
shell
[root@std40 config]# curl -XGET http://localhost:9200/_cluster/allocation/explain
{
"index": "my-index-000001",
"shard": 0,
"primary": true
}
分片恢复
shell
首先尝试手动触发自动再次分配
[root@std40 config]# curl -XPOST http://localhost:9200/_cluster/reroute?retry_failed
shell
如果分片无法自动恢复;首先用如下命令获取shard的分配情况
[root@std40 config]# curl -XGET http://localhost:9200/索引名/_shard_stores
手动尝试分配副本
shell
# 尝试分配副本
[root@std40 config]# curl -XPOST http://localhost:9200/_cluster/reroute
{
"commands": [
{
"allocate_replica": {
"index": "index1", #索引名
"shard": 3, #副本数
"node": "nodes-9" #节点名
}
}
]
}
恢复主分片
shell
# 恢复主分片
# allocate_empty_primary
# allocate_stale_primary
[root@std40 config]# curl -XPOST http://localhost:9200/_cluster/reroute
{
"commands" : [
{
"allocate_stale_primary" : {
"index" : "index42", #索引名称
"shard" : 0, #副本数
"node" : "II47uXW2QvqzHBnMcl2o_Q", # 可以写node的id或者node name
"accept_data_loss" : false # 是否允许丢失部分translog数据
}
}
]
}
调控shard的分片恢复速度
shell
[root@std40 config]# curl -XPUT http://localhost:9200/_cluster/settings
{
"transient" : {
"cluster.routing.allocation.node_concurrent_recoveries":5,
"cluster.routing.allocation.cluster_concurrent_rebalance":5,
"cluster.routing.allocation.node_initial_primaries_recoveries":2,
"indices.recovery.max_bytes_per_sec" : "1000mb"
}
}
查看es UNASSIGNED与分片信息
shell
[root@std40 config]# curl http://172.16.88.126:9200/_cat/shards?h=index,shard,prirep,state,unassigned.reason| grep UNASSIGNED
[root@std40 config]# curl -s "http://ip:9200/_cat/shards"|grep UNASSIGNED|egrep -v "^\."
查询集群的分片分配信息
[root@std40 config]# curl -XGET 'http://ip:9200/_cat/shards?v
查看es UNASSIGNED的原因(节点挂掉也会出现)
json
[root@std40 config]# curl -XGET http://172.16.88.126:9200/_cluster/allocation/explain?pretty
#解决UNASSIGNED的方法 https://blog.csdn.net/litterfrog/article/details/125298181
出现UNASSIGNED的原因:
1、分片过多,节点不够
在es集群中每个索引初始化时每个主分片的副本数+1要少于或等于节点数 r+1<=N(节点数)
2、shard默认延迟分配
在某个节点与master失去联系后,集群不会立刻重新allocation,而是会延迟一段时间确定此节点是否会重新加入集群。如果重新加入,则此节点会保持现有的分片数据,不会触发新的分片分配。
解决方法: 如果不想等待可以设置:delayed_timeout: 0
PUT /_all/_settings
{
"settings": {
"index.unassigned.node_left.delayed_timeout": "10m"
}
}
3、重启分片分配后分配过程遇到错误
https://blog.csdn.net/weixin_43820556/article/details/121489351
4、磁盘使用率超过85%
7、es集群迁移
跨集群迁移详见独立文档 Elasticsearch迁移数据.md。常用方式对比:
| 方式 | 原理 | 适用场景 |
|---|---|---|
| Snapshot & Restore | 分片级物理文件备份到共享仓库 | 数据量大、可短暂停写、需最快迁移 |
| Reindex (remote) | 目标集群 scroll 源集群 + bulk 写入 | 网络互通、数据量中等 |
| Logstash | Input scroll → Filter → Output bulk | 需过滤/transform、版本跨度大 |
| Elasticdump | HTTP 逐批读写 mapping/data | 小索引、无共享存储、运维简单 |
#mermaid-svg-yLwi0oSbkJxxfyxj{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-yLwi0oSbkJxxfyxj .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-yLwi0oSbkJxxfyxj .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-yLwi0oSbkJxxfyxj .error-icon{fill:#552222;}#mermaid-svg-yLwi0oSbkJxxfyxj .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-yLwi0oSbkJxxfyxj .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-yLwi0oSbkJxxfyxj .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-yLwi0oSbkJxxfyxj .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-yLwi0oSbkJxxfyxj .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-yLwi0oSbkJxxfyxj .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-yLwi0oSbkJxxfyxj .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-yLwi0oSbkJxxfyxj .marker{fill:#333333;stroke:#333333;}#mermaid-svg-yLwi0oSbkJxxfyxj .marker.cross{stroke:#333333;}#mermaid-svg-yLwi0oSbkJxxfyxj svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-yLwi0oSbkJxxfyxj p{margin:0;}#mermaid-svg-yLwi0oSbkJxxfyxj .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-yLwi0oSbkJxxfyxj .cluster-label text{fill:#333;}#mermaid-svg-yLwi0oSbkJxxfyxj .cluster-label span{color:#333;}#mermaid-svg-yLwi0oSbkJxxfyxj .cluster-label span p{background-color:transparent;}#mermaid-svg-yLwi0oSbkJxxfyxj .label text,#mermaid-svg-yLwi0oSbkJxxfyxj span{fill:#333;color:#333;}#mermaid-svg-yLwi0oSbkJxxfyxj .node rect,#mermaid-svg-yLwi0oSbkJxxfyxj .node circle,#mermaid-svg-yLwi0oSbkJxxfyxj .node ellipse,#mermaid-svg-yLwi0oSbkJxxfyxj .node polygon,#mermaid-svg-yLwi0oSbkJxxfyxj .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-yLwi0oSbkJxxfyxj .rough-node .label text,#mermaid-svg-yLwi0oSbkJxxfyxj .node .label text,#mermaid-svg-yLwi0oSbkJxxfyxj .image-shape .label,#mermaid-svg-yLwi0oSbkJxxfyxj .icon-shape .label{text-anchor:middle;}#mermaid-svg-yLwi0oSbkJxxfyxj .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-yLwi0oSbkJxxfyxj .rough-node .label,#mermaid-svg-yLwi0oSbkJxxfyxj .node .label,#mermaid-svg-yLwi0oSbkJxxfyxj .image-shape .label,#mermaid-svg-yLwi0oSbkJxxfyxj .icon-shape .label{text-align:center;}#mermaid-svg-yLwi0oSbkJxxfyxj .node.clickable{cursor:pointer;}#mermaid-svg-yLwi0oSbkJxxfyxj .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-yLwi0oSbkJxxfyxj .arrowheadPath{fill:#333333;}#mermaid-svg-yLwi0oSbkJxxfyxj .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-yLwi0oSbkJxxfyxj .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-yLwi0oSbkJxxfyxj .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-yLwi0oSbkJxxfyxj .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-yLwi0oSbkJxxfyxj .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-yLwi0oSbkJxxfyxj .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-yLwi0oSbkJxxfyxj .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-yLwi0oSbkJxxfyxj .cluster text{fill:#333;}#mermaid-svg-yLwi0oSbkJxxfyxj .cluster span{color:#333;}#mermaid-svg-yLwi0oSbkJxxfyxj div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-yLwi0oSbkJxxfyxj .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-yLwi0oSbkJxxfyxj rect.text{fill:none;stroke-width:0;}#mermaid-svg-yLwi0oSbkJxxfyxj .icon-shape,#mermaid-svg-yLwi0oSbkJxxfyxj .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-yLwi0oSbkJxxfyxj .icon-shape p,#mermaid-svg-yLwi0oSbkJxxfyxj .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-yLwi0oSbkJxxfyxj .icon-shape .label rect,#mermaid-svg-yLwi0oSbkJxxfyxj .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-yLwi0oSbkJxxfyxj .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-yLwi0oSbkJxxfyxj .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-yLwi0oSbkJxxfyxj :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 否
是
TB 级 + 可停写
GB 级
需 ETL/过滤
索引少且小
迁移需求
源/目标网络互通?
Elasticdump / 离线导出
数据量级?
Snapshot → Restore
Reindex remote
Logstash
yaml
https://help.aliyun.com/zh/es/use-cases/use-oss-to-migrate-data-from-a-self-managed-elasticsearch-cluster-to-an-alibaba-cloud-elasticsearch-cluster?spm=a2c4g.11186623.0.i19#task-2514918
8、查询限制
集群级别设置默认超时时间
shell
如果用户侧存在大量慢查询,且用户侧无法进行降级;则集群侧为了保证集群的稳定性可以降低集群级别的默认超时时间
# "search.default_search_timeout" : "-1", 默认值为-1
[root@std40 config]# curl -XPUT http://localhost:9200/_cluster/settings
{
"persistent": {
"search.default_search_timeout" : "800ms"
}
}
索引禁止查询
shell
在业务中存在索引混用集群的场景,由于部分不重要的或者临时可降级的索引,查询导致集群不稳定;但是业务侧没办法紧急上线处理;es侧可以该改索引进行禁止查询
#"index.blocks.read": "false", false - 允许查询 true -> 禁止查询
#"index.blocks.read_only": "false", false - 允许读写 true -> 禁止写入
#"index.blocks.read_only_allow_delete": "false", false - 允许读写 true -> 禁止写入但允许删除索引
#"index.blocks.write": "false", false - 允许写入 true -> 禁止写入 ;如果是索引写入有问题可以进行禁止写入
[root@std40 config]# curl -XPUT http://localhost:9200/索引名称/_setting
{
"index.blocks.read": "true"
}
禁止一次查询过多分片
shell
"action.destructive_requires_name" : "false"
业务按需求进行设置,出现场景,通常indexName*/_search,这种通配符查询
## 默认值为"9223372036854775807"
[root@std40 config]# curl -XPUT http://localhost:9200/_cluster/settings
{
"persistent": {
"action.search.shard_count.limit" : "2000"
}
}
熔断设置
shell
#熔断机制:
使用熔断机制来防止某些操作消耗过多的内存而导致集群不稳定。熔断器是一种防止某些资源(如内存、CPU等)过度消耗的保护机制。
这些设置指定了不同类型的内存使用阈值。当某些操作的内存消耗超过这些阈值时,Elasticsearch 会中止该操作,并抛出错误或警告,以保护集群免受内存溢出的影响
#参数详解:
#indices.breaker.fielddata.limit:
这个设置控制了字段数据(fielddata)使用的内存量的上限。当字段数据的内存使用量超过这个限制时,Elasticsearch 会触发熔断机制来防止内存过载。默认值为60%。此处的"40%"表示允许字段数据使用最多集群总内存的 40%。
#indices.breaker.request.limit:
这个设置限制了请求的内存使用。它控制了单个查询请求(例如 search 请求)可以使用的最大内存量。如果请求的内存使用超过这个阈值,系统会触发熔断机制。默认值为60%。此处的"40%":表示请求的内存使用量不能超过集群总内存的 40%。
#indices.breaker.total.limit:
这个设置限制了 Elasticsearch 集群总的内存使用量。它定义了集群可以使用的最大内存量的百分比。一旦集群的内存使用超过这个限制,所有新的请求会被阻止。默认值为70%。"50%":表示总内存使用量不能超过集群总内存的 50%。
#设置熔断
[root@std40 config]# curl -XPUT http://localhost:9200/_cluster/settings
{
"persistent": {
"indices.breaker.fielddata.limit": "40%",
"indices.breaker.request.limit": "40%",
"indices.breaker.total.limit": "50%"
}
}
9、分片均衡限制
集群级别均衡限制
shell
"cluster.routing.allocation.enable": "all",
#设置值:"all"
#含义:这个参数控制 Elasticsearch 是否允许分配新的分片(primary 和 replica)到节点上。"all" 表示允许分配所有类型的分片,包括主分片和副本分片。
#作用:当设置为 "all" 时,集群的分片分配会按正常方式进行。如果修改此设置为 "primaries","replicas" 或 "none",可以限制分片的分配,控制集群的负载和资源使用。
"cluster.routing.rebalance.enable": "none",
#设置值:"none"
#含义:这个参数控制集群在节点负载不均衡时,是否会重新平衡分片。"none" 表示不允许 Elasticsearch 执行自动的分片重新平衡。
#作用:当设置为 "none" 时,Elasticsearch 将不会执行分片的自动重新平衡,所有分片都将保持在其当前的节点上,不会进行任何调整。
[root@std40 config]# curl -XPUT http://localhost:9200/_cluster/settings
{
"persistent": {
"cluster.routing.allocation.enable": "all",
"cluster.routing.rebalance.enable": "none"
}
}
手动移动分片
shell
[root@std40 config]# curl -XPOST http://localhost:9200/_cluster/reroute
{
"commands": [
{
"move": {
"index": "index1", #索引名称
"shard": 37, #分片数
"from_node": "nodes-71", #源节点
"to_node": "nodes-35" #目标节点
}
}
]
}
[root@std40 config]# curl -XPOST "http://localhost:9200/_cluster/reroute" -H 'Content-Type: application/json' -d'{ "commands": [ { "move": { "index": "index1", "shard": 37, "from_node": "nodes-71", "to_node": "nodes-35" } } ]}'
索引级别均衡限制
shell
index.routing.rebalance.enable
#设置值:"primaries"
#含义:这个参数控制索引的分片分配策略。
"primaries":表示只会分配主分片(primary shards)。副本分片(replica shards)将不会被分配。这对于在某些情况下只关心主分片的负载或故障恢复时使用。
"all":表示主分片和副本分片都可以分配。
"none":表示不允许任何分片分配(对于暂时关闭索引或维护时很有用)。
#作用:通过将 index.routing.allocation.enable 设置为 "primaries",Es 只允许主分片进行分配,而副本分片不会被分配。这在一些特殊情况下可能有用,比如希望只在某些节点上运行主分片,或者在某些时候避免副本分片的分配以节省资源。
index.routing.rebalance.enable:
#设置值:"none"
#含义:这个参数控制是否允许 Elasticsearch 自动进行分片的重新平衡(rebalance)。
"none":禁用自动重平衡。也就是说,集群不会自动迁移分片以平衡节点之间的负载。
"primaries":允许主分片进行重平衡。
"replicas":允许副本分片进行重平衡。
"all":允许主分片和副本分片都进行重平衡。
#作用:通过将 index.routing.rebalance.enable 设置为 "none",Es会禁止任何自动的分片重平衡操作。这意味着,即使集群的负载不均衡,分片也不会自动迁移到其他节点。这通常用于减少在负载不均或临时故障时的自动调整,防止影响集群的稳定性。
# _all所有索引,或者写索引名称通配符,或者写具体索引名称
[root@std40 config]# curl -XPUT http://localhost:9200/_all/_settings
{
"index.routing.allocation.enable": "primaries",
"index.routing.rebalance.enable": "none"
}
索引级别强制均衡度限制
shell
# 具体数字依据节点数和索引shard数目来定
[root@std40 config]# curl -XPUT http://localhost:9200/索引名/_settings
{
"index.routing.allocation.total_shards_per_node": 5
}
10、数据迁移
分片迁移
shell
[root@std40 config]# curl -XPUT http://localhost:9200/_cluster/settings
{
"persistent": {
"cluster.routing.allocation.exclude._name":"node-11"
}
}
[root@std40 config]# curl -H "Content-Type: application/json" -XPUT _cluster/settings -d '{
"cluster.routing.allocation.include._name" : "云上集群节点名称列表",
"cluster.routing.allocation.exclude._name" : "自建集群节点名称列表"
}'
分片迁移进度查看
shell
[root@std40 config]# curl -XGET http://localhost:9200/_cat/recovery?active_only&v
分片迁移加速
shell
默认40mb,并发默认为2,可以适当调大,如果集群压力比较大,则调小
[root@std40 config]# curl -XPUT http://localhost:9200/_cluster/settings
{
"persistent": {
"cluster.routing.allocation.node_concurrent_recoveries": 2,
"indices.recovery.max_bytes_per_sec": "40mb/s"
}
}
shell
[root@std40 config]# curl -XPUT http://localhost:9200/_cluster/settings
{
"transient" : {
"indices.recovery.max_bytes_per_sec" : "200mb"
}
}
查看节点上是否还有数据
shell
[root@std40 config]# curl -XGET http://localhost:9200/_cat/allocation?v
11、节点重建
如果是云盘重建节点,可以设置索引延迟分配,方便节点恢复后原地恢复数据
shell
[root@std40 config]# curl -XPUT http://localhost:9200/索引名称/_settings
{
"index.unassigned.node_left.delayed_timeout": "20m"
}
## 设置所有索引,默认为1min钟
[root@std40 config]# curl -XPUT http://localhost:9200/_all/_settings
{
"index.unassigned.node_left.delayed_timeout": "20m"
}
12、紧急变配处理
shell
建议用户停写,停写之后,可以执行如下命令,使得数据都落盘,避免需要回放translog
[root@std40 config]# curl -XPOST http://localhost:9200/_flush/synced
13、快照备份与恢复
快照原理
Snapshot 不是 简单的文件拷贝,而是对分片 Lucene 文件的增量、一致性备份:
- 快照开始时,各分片执行 flush(或利用已有 commit point),获得一致的 segment 视图。
- 仅上传尚未存在于仓库中的 segment 文件(增量)。
- 元数据(索引 settings、mapping、别名)可选写入
include_global_state。 - Restore 时在目标集群重建索引结构 ,从仓库拉取 segment 文件,速度受
max_restore_bytes_per_sec与带宽限制。
#mermaid-svg-kBsnpJm9f2EydGPj{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-kBsnpJm9f2EydGPj .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-kBsnpJm9f2EydGPj .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-kBsnpJm9f2EydGPj .error-icon{fill:#552222;}#mermaid-svg-kBsnpJm9f2EydGPj .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-kBsnpJm9f2EydGPj .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-kBsnpJm9f2EydGPj .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-kBsnpJm9f2EydGPj .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-kBsnpJm9f2EydGPj .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-kBsnpJm9f2EydGPj .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-kBsnpJm9f2EydGPj .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-kBsnpJm9f2EydGPj .marker{fill:#333333;stroke:#333333;}#mermaid-svg-kBsnpJm9f2EydGPj .marker.cross{stroke:#333333;}#mermaid-svg-kBsnpJm9f2EydGPj svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-kBsnpJm9f2EydGPj p{margin:0;}#mermaid-svg-kBsnpJm9f2EydGPj .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-kBsnpJm9f2EydGPj .cluster-label text{fill:#333;}#mermaid-svg-kBsnpJm9f2EydGPj .cluster-label span{color:#333;}#mermaid-svg-kBsnpJm9f2EydGPj .cluster-label span p{background-color:transparent;}#mermaid-svg-kBsnpJm9f2EydGPj .label text,#mermaid-svg-kBsnpJm9f2EydGPj span{fill:#333;color:#333;}#mermaid-svg-kBsnpJm9f2EydGPj .node rect,#mermaid-svg-kBsnpJm9f2EydGPj .node circle,#mermaid-svg-kBsnpJm9f2EydGPj .node ellipse,#mermaid-svg-kBsnpJm9f2EydGPj .node polygon,#mermaid-svg-kBsnpJm9f2EydGPj .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-kBsnpJm9f2EydGPj .rough-node .label text,#mermaid-svg-kBsnpJm9f2EydGPj .node .label text,#mermaid-svg-kBsnpJm9f2EydGPj .image-shape .label,#mermaid-svg-kBsnpJm9f2EydGPj .icon-shape .label{text-anchor:middle;}#mermaid-svg-kBsnpJm9f2EydGPj .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-kBsnpJm9f2EydGPj .rough-node .label,#mermaid-svg-kBsnpJm9f2EydGPj .node .label,#mermaid-svg-kBsnpJm9f2EydGPj .image-shape .label,#mermaid-svg-kBsnpJm9f2EydGPj .icon-shape .label{text-align:center;}#mermaid-svg-kBsnpJm9f2EydGPj .node.clickable{cursor:pointer;}#mermaid-svg-kBsnpJm9f2EydGPj .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-kBsnpJm9f2EydGPj .arrowheadPath{fill:#333333;}#mermaid-svg-kBsnpJm9f2EydGPj .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-kBsnpJm9f2EydGPj .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-kBsnpJm9f2EydGPj .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-kBsnpJm9f2EydGPj .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-kBsnpJm9f2EydGPj .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-kBsnpJm9f2EydGPj .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-kBsnpJm9f2EydGPj .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-kBsnpJm9f2EydGPj .cluster text{fill:#333;}#mermaid-svg-kBsnpJm9f2EydGPj .cluster span{color:#333;}#mermaid-svg-kBsnpJm9f2EydGPj div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-kBsnpJm9f2EydGPj .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-kBsnpJm9f2EydGPj rect.text{fill:none;stroke-width:0;}#mermaid-svg-kBsnpJm9f2EydGPj .icon-shape,#mermaid-svg-kBsnpJm9f2EydGPj .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-kBsnpJm9f2EydGPj .icon-shape p,#mermaid-svg-kBsnpJm9f2EydGPj .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-kBsnpJm9f2EydGPj .icon-shape .label rect,#mermaid-svg-kBsnpJm9f2EydGPj .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-kBsnpJm9f2EydGPj .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-kBsnpJm9f2EydGPj .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-kBsnpJm9f2EydGPj :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 目标集群
快照仓库 S3/OSS/NFS
源集群
snapshot
增量上传
restore
restore
索引分片
快照元数据
Segment 文件
恢复后的索引
s3远程快照仓库
帮助用户做远程快照迁移
获取集群中所有快照仓库信息
shell
[root@std40 config]# curl -XGET http://localhost:9200/_snapshot
获取具体仓库信息
shell
[root@std40 config]# curl -XGET http://localhost:9200/_snapshot/auto_snapshot
创建快照仓库
shell
[root@std40 config]# curl -XPUT http://localhost:9200/_snapshot/test_snapshot
{
"type" : "s3", #类型
"settings" : {
"bucket" : "elasticsearch-snapshot-cn-north-1", #桶名
"base_path" : "es-xxxxx/xxxxx", #路径
"endpoint" : "s3-internal.cn-north-1.xxxxx-oss.com", #地址
"protocol" : "http",
"compress" : "true",
"access_key": "xxxxxxxxxxxxx",
"secret_key": "xxxxxxxxxxxx", # s3密钥
"max_restore_bytes_per_sec" : "200mb", # 快照恢复速度
"max_snapshot_bytes_per_sec" : "100mb" # 快照速度
}
}
创建快照
shell
[root@std40 config]# curl -XPUT http://localhost:9200/_snapshot/test_snapshot/snapshot_2
{
"indices": "index_1,index_2",
"ignore_unavailable": true,
"include_global_state": false,
"metadata": {
"taken_by": "user123",
"taken_because": "backup before upgrading"
}
}
shell
[root@std40 config]# curl -XPUT http://localhost:9200/_snapshot/auto_snapshot/snapshot_2
{
"indices": "*",
"ignore_unavailable": true,
"include_global_state": false
}
查看快照进度
shell
[root@std40 config]# curl -XGET http://localhost:9200/_snapshot/_status
[root@std40 config]# curl -XGET http://localhost:9200/_snapshot/<repository>/_status
[root@std40 config]# curl -XGET http://localhost:9200/_snapshot/<repository>/<snapshot>/_status
快照恢复
shell
# auto_snapshot 为仓库名称
# snapshot_name 替换为 用户界面的快照名称 auto_snapshot_20240509190034
[root@std40 config]# curl -XPOST http://localhost:9200/_snapshot/auto_snapshot/snapshot_name/_restore
{
#"indices": "index_*",可以使用通配符
"indices": "index_1,index_2",
"ignore_unavailable": true,
"include_global_state": false,
"include_aliases": false
}
14、其他类运维api
索引forcemerge
shell
#这条命令的意思如下:
1、对指定的索引执行 强制合并 操作,合并过程中会将不必要的段合并为最多 100 个段。
2、only_expunge_deletes=false:不仅仅合并删除标记的文档所在的段,还会合并所有段。
3、flush=true:在合并完成后强制刷新索引,以确保数据被持久化并更新到搜索中。
#使用场景
优化存储:当索引中的许多文档被删除后,Elasticsearch 并不会立即回收这些删除的空间, _forcemerge 可以帮助合并段并回收空间,优化磁盘使用。
性能优化:如果索引经过多次写入、删除操作,可能会有很多小段,执行 _forcemerge 可以合并为更少的段,减少搜索时的开销。
[root@std40 config]# curl -XPOST http://localhost:9200/索引名/_forcemerge?only_expunge_deletes=false&max_num_segments=100&flush=true
查看哪些字段fielddata占用的堆内存比较大
shell
# 查看
[root@std40 config]# curl -XGET "http://localhost:9200/_cat/fielddata?v&s=size:desc"
id host ip node field size
czX0QS8bQeC8B2k6UCrx6w 192.168.30.15 192.168.30.15 192.168.30.15 streams 0b
H0dkLtkNRd2Y8ivFzXWDbw 192.168.30.14 192.168.30.14 192.168.30.14 streams 0b
# 清理
[root@std40 config]# curl -XPOST http://localhost:9200/*/_cache/clear?fielddata=true
reindex
shell
#从一个索引中复制数据到另一个索引。具体来说,这个命令将从 twitter 索引中根据指定条件筛选出一些文档,然后将这些文档重新索引到 new_twitter 索引中。
# slices等于源索引的分片个数, 在执行重新索引时将任务拆分成 5 个并行任务,以加速处理,并发执行
[root@std40 config]# curl -XPOST http://localhost:9200/_reindex?slices=5
{
"source": {
"index": "twitter",
"size": 10000,
"query": {
"range": {
"modify_time": {
"gte": 0,
"lte": 1595040614196
}
}
}
},
"dest": {
"index": "new_twitter"
}
}
esdump索引数据导出
elasticdump 通过 HTTP Bulk API 逐批读写 ES 数据,本质是应用层迁移,不依赖共享存储。
导出顺序与原理
必须按 analyzer → mapping → data 顺序,原因:
- analyzer:自定义分词器定义在 index settings 中,需先创建索引骨架。
- mapping :字段类型、analyzer 绑定关系;若先导 data,ES 会 dynamic mapping 自动推断类型,可能与源集群不一致(如
long变text)。 - data :bulk 写入文档;
--limit控制每批条数,影响速度与index.max_result_window(scroll/search 窗口)。
#mermaid-svg-54ujMvrc7CX5dtQa{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-54ujMvrc7CX5dtQa .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-54ujMvrc7CX5dtQa .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-54ujMvrc7CX5dtQa .error-icon{fill:#552222;}#mermaid-svg-54ujMvrc7CX5dtQa .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-54ujMvrc7CX5dtQa .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-54ujMvrc7CX5dtQa .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-54ujMvrc7CX5dtQa .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-54ujMvrc7CX5dtQa .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-54ujMvrc7CX5dtQa .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-54ujMvrc7CX5dtQa .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-54ujMvrc7CX5dtQa .marker{fill:#333333;stroke:#333333;}#mermaid-svg-54ujMvrc7CX5dtQa .marker.cross{stroke:#333333;}#mermaid-svg-54ujMvrc7CX5dtQa svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-54ujMvrc7CX5dtQa p{margin:0;}#mermaid-svg-54ujMvrc7CX5dtQa .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-54ujMvrc7CX5dtQa .cluster-label text{fill:#333;}#mermaid-svg-54ujMvrc7CX5dtQa .cluster-label span{color:#333;}#mermaid-svg-54ujMvrc7CX5dtQa .cluster-label span p{background-color:transparent;}#mermaid-svg-54ujMvrc7CX5dtQa .label text,#mermaid-svg-54ujMvrc7CX5dtQa span{fill:#333;color:#333;}#mermaid-svg-54ujMvrc7CX5dtQa .node rect,#mermaid-svg-54ujMvrc7CX5dtQa .node circle,#mermaid-svg-54ujMvrc7CX5dtQa .node ellipse,#mermaid-svg-54ujMvrc7CX5dtQa .node polygon,#mermaid-svg-54ujMvrc7CX5dtQa .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-54ujMvrc7CX5dtQa .rough-node .label text,#mermaid-svg-54ujMvrc7CX5dtQa .node .label text,#mermaid-svg-54ujMvrc7CX5dtQa .image-shape .label,#mermaid-svg-54ujMvrc7CX5dtQa .icon-shape .label{text-anchor:middle;}#mermaid-svg-54ujMvrc7CX5dtQa .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-54ujMvrc7CX5dtQa .rough-node .label,#mermaid-svg-54ujMvrc7CX5dtQa .node .label,#mermaid-svg-54ujMvrc7CX5dtQa .image-shape .label,#mermaid-svg-54ujMvrc7CX5dtQa .icon-shape .label{text-align:center;}#mermaid-svg-54ujMvrc7CX5dtQa .node.clickable{cursor:pointer;}#mermaid-svg-54ujMvrc7CX5dtQa .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-54ujMvrc7CX5dtQa .arrowheadPath{fill:#333333;}#mermaid-svg-54ujMvrc7CX5dtQa .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-54ujMvrc7CX5dtQa .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-54ujMvrc7CX5dtQa .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-54ujMvrc7CX5dtQa .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-54ujMvrc7CX5dtQa .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-54ujMvrc7CX5dtQa .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-54ujMvrc7CX5dtQa .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-54ujMvrc7CX5dtQa .cluster text{fill:#333;}#mermaid-svg-54ujMvrc7CX5dtQa .cluster span{color:#333;}#mermaid-svg-54ujMvrc7CX5dtQa div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-54ujMvrc7CX5dtQa .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-54ujMvrc7CX5dtQa rect.text{fill:none;stroke-width:0;}#mermaid-svg-54ujMvrc7CX5dtQa .icon-shape,#mermaid-svg-54ujMvrc7CX5dtQa .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-54ujMvrc7CX5dtQa .icon-shape p,#mermaid-svg-54ujMvrc7CX5dtQa .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-54ujMvrc7CX5dtQa .icon-shape .label rect,#mermaid-svg-54ujMvrc7CX5dtQa .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-54ujMvrc7CX5dtQa .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-54ujMvrc7CX5dtQa .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-54ujMvrc7CX5dtQa :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} analyzer.json
mapping.json
data.json
目标集群索引
1、导出分词
导出分词器,导出分词器的时候要特别注意,我们只能根据索引单个导入,不能全部导出,全部导出会出现索引不存在的错误:https://blog.csdn.net/Wang_Ocean/article/details/90267797
shell
/export/server/icos-elasticsearch/elasticdump/elasticsearch-dump/bin/elasticdump --input http://icos:2y5CJH9S660ao70r3@10.20.0.7:9200/cityos-oss*(索引名) --output /export/cityososs_analyzer.json --type=analyzer --limit=10000
2、导出结构
shell
/export/server/icos-elasticsearch/elasticdump/elasticsearch-dump/bin/elasticdump --input http://icos:2y5CJH9S660ao70r3@10.20.0.7:9200/cityos-oss*(索引名) --output /export/cityososs_mapping.json --type=mapping --limit=10000 #导出结构
3、导出数据
shell
/export/server/icos-elasticsearch/elasticdump/elasticsearch-dump/bin/elasticdump --input http://icos:2y5CJH9S660ao70r3@10.20.0.7:9200/cityos-oss*(索引名) --output /export/cityososs_data.json --type=data --limit=10000 #导出数据
多个索引导出脚本
导出
shell
#unidom.txt文件放置es索引名
#!/bin/bash
for item in `cat /root/unidom.txt`
do
/export/server/icos-elasticsearch/elasticdump/elasticsearch-dump/bin/elasticdump --input http://icos:2y5CJH9S660ao70r3@10.20.0.8:9200/$item --output /export/unidom/analyzer/${item}_analyzer.json --type=analyzer --limit=10000
/export/server/icos-elasticsearch/elasticdump/elasticsearch-dump/bin/elasticdump --input http://icos:2y5CJH9S660ao70r3@10.20.0.8:9200/$item --output /export/unidom/mapping/${item}_mapping.json --type=mapping --limit=10000
/export/server/icos-elasticsearch/elasticdump/elasticsearch-dump/bin/elasticdump --input http://icos:2y5CJH9S660ao70r3@10.20.0.8:9200/$item --output /export/unidom/data/${item}_data.json --type=data --limit=10000
done
esdump索引数据导入
0、如果索引不存在,则先创建索引
shell
curl -X PUT http://10.241.241.187:9200/test -uicos:2y5CJH9S660ao70r3
0.0、如果创建后导入分词时报如下错误,则删除掉第一步创建的索引,重新导入分词即可
shell
Error Emitted => {"error":{"root_cause":[{"type":"resource_already_exists_exception","reason":"index [huizhanyun-search-test-v1/Z_KdZNpTSeyyzu1dGr5Lnw] already exists","index_uuid":"Z_KdZNpTSeyyzu1dGr5Lnw","index":"huizhanyun-search-test-v1"}],"type":"resource_already_exists_exception","reason":"index [huizhanyun-search-test-v1/Z_KdZNpTSeyyzu1dGr5Lnw] already exists","index_uuid":"Z_KdZNpTSeyyzu1dGr5Lnw","index":"huizhanyun-search-test-v1"},"status":400}
Fri, 17 Nov 2023 09:42:37 GMT | Error Emitted => {"error":{"root_cause":[{"type":"resource_already_exists_exception","reason":"index [huizhanyun-search-test-v1/Z_KdZNpTSeyyzu1dGr5Lnw] already exists","index_uuid":"Z_KdZNpTSeyyzu1dGr5Lnw","index":"huizhanyun-search-test-v1"}],"type":"resource_already_exists_exception","reason":"index [huizhanyun-search-test-v1/Z_KdZNpTSeyyzu1dGr5Lnw] already exists","index_uuid":"Z_KdZNpTSeyyzu1dGr5Lnw","index":"huizhanyun-search-test-v1"},"status":400}
Fri, 17 Nov 2023 09:42:37 GMT | Total Writes: 0
Fri, 17 Nov 2023 09:42:37 GMT | dump ended with error (get phase) => BAD_REQUEST: {"error":{"root_cause":[{"type":"resource_already_exists_exception","reason":"index [huizhanyun-search-test-v1/Z_KdZNpTSeyyzu1dGr5Lnw] already exists","index_uuid":"Z_KdZNpTSeyyzu1dGr5Lnw","index":"huizhanyun-search-test-v1"}],"type":"resource_already_exists_exception","reason":"index [huizhanyun-search-test-v1/Z_KdZNpTSeyyzu1dGr5Lnw] already exists","index_uuid":"Z_KdZNpTSeyyzu1dGr5Lnw","index":"huizhanyun-search-test-v1"},"status":400}
1、导入分词
shell
/export/server/icos-elasticsearch/elasticdump/elasticsearch-dump/bin/elasticdump --input /export/server/icos-elasticsearch/elasticdump/data/cityososs_analyzer.json --output http://icos:2y5CJH9S660ao70r3@10.20.0.74:9200/cityos-oss* --type=analyzer --limit=10000
2、导入结构
shell
/export/server/icos-elasticsearch/elasticdump/elasticsearch-dump/bin/elasticdump --input /export/server/icos-elasticsearch/elasticdump/data/cityososs_mapping.json --output http://icos:2y5CJH9S660ao70r3@10.20.0.74:9200/cityos-oss* --type=mapping --limit=10000
3、导入数据
shell
/export/server/icos-elasticsearch/elasticdump/elasticsearch-dump/bin/elasticdump --input /export/server/icos-elasticsearch/elasticdump/data/cityososs_data.json --output http://icos:2y5CJH9S660ao70r3@10.20.0.74:9200/cityos-oss* --type=data --limit=1000(这个可以根据数据的大小来调整每次导入的数量)
多个es索引导入脚本
如果索引不存在,则先创建索引
shell
curl -X PUT http://10.241.241.187:9200/test -uicos:2y5CJH9S660ao70r3
先导入analyzer分词
shell
#!/bin/bash
for item in `ls /export/cityos-oss/analyzer |awk -F'_' '{print $1}'`
do
/export/server/icos-elasticsearch/elasticdump/elasticsearch-dump/bin/elasticdump --input /export/cityos-oss/analyzer/${item}_analyzer.json --output http://icos:H466b7qB96iYc656G@172.31.18.36:9200/$item --type=analyzer
done
导入mapping
shell
#!/bin/bash
for item in `ls /export/cityos-oss/mapping |awk -F'_' '{print $1}'`
do
/export/server/icos-elasticsearch/elasticdump/elasticsearch-dump/bin/elasticdump --input /export/cityos-oss/mapping/${item}_mapping.json --output http://icos:H466b7qB96iYc656G@172.31.18.36:9200/$item --type=mapping
done
导入data
shell
#!/bin/bash
for item in `ls /export/cityos-oss/data |awk -F'_' '{print $1}'`
do
/export/server/icos-elasticsearch/elasticdump/elasticsearch-dump/bin/elasticdump --input /export/cityos-oss/data/${item}_data.json --output http://icos:H466b7qB96iYc656G@172.31.18.36:9200/$item --type=data
done
安装elasticdump备份插件
yml
有网安装方法:
yum -y install npm nodejs
npm换源
npm config set registry https://registry.npmmirror.com/
npm按照elasticdump
npm install elasticdump -g
内网安装方法:
解压elasticdump-arm.zip包即可使用
https://www.codenong.com/cs107048106/(包含安装elasticdump和数据备份、还原、迁移)
具体实施步骤:
# 下载安装包
wget https://nodejs.org/dist/v10.13.0/node-v10.13.0-linux-x64.tar.xz
# 解压
xz -d node-v10.13.0-linux-x64.tar.xz
tar xvf node-v10.13.0-linux-x64.tar
# 建立文件软连接到系统命令
ln -s /root/node-v10.13.0-linux-x64/bin/node /usr/bin/node
ln -s /root/node-v10.13.0-linux-x64/bin/npm /usr/bin/npm
# 检查是否安装成功
node -v
npm -v
#下载elasticdump
wget https://github.com/elasticsearch-dump/elasticsearch-dump/releases/download/v6.99.7/elasticsearch-dump-6.99.7.tar.gz
#解压
tar -zxvf elasticsearch-dump-6.99.7.tar.gz
#安装
npm install -g /path/to/elasticsearch-dump-6.99.7
总结
集群 Red/Yellow 排查流程
#mermaid-svg-rayFuIAZj2LIMkce{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-rayFuIAZj2LIMkce .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-rayFuIAZj2LIMkce .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-rayFuIAZj2LIMkce .error-icon{fill:#552222;}#mermaid-svg-rayFuIAZj2LIMkce .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-rayFuIAZj2LIMkce .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-rayFuIAZj2LIMkce .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-rayFuIAZj2LIMkce .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-rayFuIAZj2LIMkce .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-rayFuIAZj2LIMkce .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-rayFuIAZj2LIMkce .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-rayFuIAZj2LIMkce .marker{fill:#333333;stroke:#333333;}#mermaid-svg-rayFuIAZj2LIMkce .marker.cross{stroke:#333333;}#mermaid-svg-rayFuIAZj2LIMkce svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-rayFuIAZj2LIMkce p{margin:0;}#mermaid-svg-rayFuIAZj2LIMkce .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-rayFuIAZj2LIMkce .cluster-label text{fill:#333;}#mermaid-svg-rayFuIAZj2LIMkce .cluster-label span{color:#333;}#mermaid-svg-rayFuIAZj2LIMkce .cluster-label span p{background-color:transparent;}#mermaid-svg-rayFuIAZj2LIMkce .label text,#mermaid-svg-rayFuIAZj2LIMkce span{fill:#333;color:#333;}#mermaid-svg-rayFuIAZj2LIMkce .node rect,#mermaid-svg-rayFuIAZj2LIMkce .node circle,#mermaid-svg-rayFuIAZj2LIMkce .node ellipse,#mermaid-svg-rayFuIAZj2LIMkce .node polygon,#mermaid-svg-rayFuIAZj2LIMkce .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-rayFuIAZj2LIMkce .rough-node .label text,#mermaid-svg-rayFuIAZj2LIMkce .node .label text,#mermaid-svg-rayFuIAZj2LIMkce .image-shape .label,#mermaid-svg-rayFuIAZj2LIMkce .icon-shape .label{text-anchor:middle;}#mermaid-svg-rayFuIAZj2LIMkce .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-rayFuIAZj2LIMkce .rough-node .label,#mermaid-svg-rayFuIAZj2LIMkce .node .label,#mermaid-svg-rayFuIAZj2LIMkce .image-shape .label,#mermaid-svg-rayFuIAZj2LIMkce .icon-shape .label{text-align:center;}#mermaid-svg-rayFuIAZj2LIMkce .node.clickable{cursor:pointer;}#mermaid-svg-rayFuIAZj2LIMkce .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-rayFuIAZj2LIMkce .arrowheadPath{fill:#333333;}#mermaid-svg-rayFuIAZj2LIMkce .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-rayFuIAZj2LIMkce .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-rayFuIAZj2LIMkce .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-rayFuIAZj2LIMkce .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-rayFuIAZj2LIMkce .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-rayFuIAZj2LIMkce .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-rayFuIAZj2LIMkce .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-rayFuIAZj2LIMkce .cluster text{fill:#333;}#mermaid-svg-rayFuIAZj2LIMkce .cluster span{color:#333;}#mermaid-svg-rayFuIAZj2LIMkce div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-rayFuIAZj2LIMkce .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-rayFuIAZj2LIMkce rect.text{fill:none;stroke-width:0;}#mermaid-svg-rayFuIAZj2LIMkce .icon-shape,#mermaid-svg-rayFuIAZj2LIMkce .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-rayFuIAZj2LIMkce .icon-shape p,#mermaid-svg-rayFuIAZj2LIMkce .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-rayFuIAZj2LIMkce .icon-shape .label rect,#mermaid-svg-rayFuIAZj2LIMkce .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-rayFuIAZj2LIMkce .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-rayFuIAZj2LIMkce .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-rayFuIAZj2LIMkce :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 节点恢复/扩节点
磁盘满
副本过多
仍失败
是
否
发现 status 异常
GET /_cluster/health?level=indices
GET /_cat/shards 找 UNASSIGNED
GET /_cluster/allocation/explain
能否自动修复?
等待 delayed_timeout
扩容 + 解除 read_only_allow_delete
调低 number_of_replicas
POST /_cluster/reroute?retry_failed
主分片仍丢失?
reindex 到新索引 + 别名切换
Green
yaml
遇到集群Red、Yellow时,我们可以从如下方法排查:
集群层面:curl -s 172.31.30.28:9200/_cat/nodes 或者 GET /_cluster/health
索引层面:GET /_cluster/health?pretty&level=indices
分片层面:GET /_cluster/health?pretty&level=shards
恢复情况:GET /_recovery?pretty
有unassigned分片的排查思路 :
先诊断:GET /_cluster/allocation/explain
#重新分配: /_cluster/reroute
实在无法分配,索引重建:
1.1、新建备份索引:
curl -XPUT 'http://xxxx:9200/a_index_copy/' -d '{ "settings":{ "index":{ "number_of_shards":3, "number_of_replicas":1 } } }
1.2、通过reindex api将a_index数据copy到a_index_copy:
POST _reindex { "source": { "index": "a_index" }, "dest": { "index": "a_index_copy", "op_type": "create" } }
1.3、删除a_index索引,这个必须要先做,否则别名无法添加
curl -XDELETE 'http://xxxx:9200/a_index'
1.4、给a_index_copy添加别名a_index
curl -XPOST 'http://xxxx:9200/_aliases' -d ' { "actions": [ {"add": {"index": "a_index_copy", "alias": "a_index"}} ] }'
排错
1、/export/server/elasticsearch-6.8.13/plugins/plugins.zip/plugin-descriptor.properties: Not a directory
yaml
移除/export/server/elasticsearch-6.8.13/plugins/下的plugins.zip这个重启即可。
2、以root启动报错
yaml
用elasticsearch用户启动解决问题
3、"cannot allocate because a previous copy of the primary shard existed but can no longer be found on the nodes
yaml
查看es节点是否存活、查看索引的主分片的副本数是不是大于了节点数
4、es磁盘满了之后重新给es磁盘扩容,扩容完成后,发现es写不进去,具体报错如下
Caused by: org.springframework.data.elasticsearch.ElasticsearchException: Bulk indexing has failures. Use ElasticsearchException.getFailedDocuments() for detailed messages {44499=ElasticsearchException\[Elasticsearch exception \[type=cluster_block_exception, reason=blocked by: \[FORBIDDEN/12/index read-only / allow delete (api);]]}]
解决方法:
json
1、查看
get http://xxx.xxx.xxx.xxx:9200/_settings
2、结果
blocks:{
read_only_allow_delete:true
}
true:代表只读
false:代表正常所有 权限
3、解决
curl -XPUT -H "Content-Type: application/json" http://127.0.0.1:9200/_all/_settings -d '{"index.blocks.read_only_allow_delete": false}'
```
5、集群状态red,有索引主分片未分配;es集群状态为yellow,有索引副本分片未分配
yaml
es集群状态共有三种:
red,yellow,green,
集群正常状态为green,状态会根据索引异常状态变化,优先显示最严重的情况,
例如:
集群中没有yellow和red状态索引,就是正常状态,呈green状态;
只有yellow索引,集群呈yellow状态;
只有red索引,呈red状态;同时存在red状态索引和yellow状态索引,集群呈red状态。
通过 curl -XGET http://localhost:9200/_cluster/allocation/explain?pretty 命令查看集群 red 或 yellow 原因。
yaml
异常状态可能的原因:
磁盘问题导致:
集群每个节点的磁盘水位超过低水位(默认85%),索引副本分片无法分配,索引会变yellow状态;每个节点的磁盘水位超过高水位(默认90%),新建索引的主分片无法分配,索引呈red状态---》扩容或者清理数据
单节点离线:
集群索引都设置有副本,单节点离线会导致集群状态yellow;存在0副本索引,单节点离线会导致集群状态red
创建索引:
新索引(有副本的)在创建初始化期间,也会短时yellow;0副本则会短时red。
索引settings设置不合理:
索引设置中total_shards_per_node(限制集群每个节点上只能分配该索引的几个片)值设置不合理,也会导致索引分片无法分配的情况,比如:集群3个data节点,索引分片设置的3主1副(共6个分片),索引settings指定total_shards_per_node:1(每个节点只能分配1个片,3个节点就只能分配3个片),索引将会有3个副本分片无法分配,呈yellow状态;再比如:集群3个data节点,索引分片设置6主1副,索引settings指定total_shards_per_node:1,集群只能分配该索引的3个片,会有三个主分片和6个副本分片无法分配,有主分片无法分配,索引呈red状态
yaml
调整索引分片数
索引主分片数量调整
新建索引时,可指定索引主分片和副本分片,例如:
# 新建索引
PUT test
{
"settings": {
"index": {#
"number_of_shards": "5",
"number_of_replicas": "1"
}
}
}
# 对于按日期进行拆分的索引,可以通过修改索引模板的方式,来修改之后创建的索引的主分片数量
# 比如 test*类索引,test-2022.11.11 索引为5主1副,想更改后续索引的主分片数,可以调整索引模板设置,比如调整为 10主1副,后一天创建的索引 test-2022.10.12 就会应用上新索引模板中的设置,变为 10主1副了
PUT _template/test_template
{
"order" : 1000,
"index_patterns" : [
"test*"
],
"settings" : {
"index" : {
"number_of_shards" : "10",
"number_of_replicas" : "1"
}
},
"mappings" : {
},
"aliases" : {
}
}
注意:
对于已经创建的索引,无法直接修改索引主分片数量,若要修改,可以使用 reindex 的方法重建索引,reindex 可参考官方文档:https://www.elastic.co/guide/en/elasticsearch/reference/6.8/docs-reindex.html
索引副本分片数量调整
es 中的索引默认副本分片数量为 1,即每个主分片都会有一个副本分片,这样主分片在丢失的情况下,副本分片可提升为主分片,保证数据的高可用。
索引的主分片一旦设定,后面是不可以更改的,但是索引的副本分片的数量是可以动态修改的,修改命令,示例如下:
# 可登录 es 集群图形化界面工具 kibana 或 head 调用执行 api 命令
# 查看索引情况
GET _cat/indices?v
# 查看具体索引情况
GET _cat/indices/索引名称?v
# 修改索引副本分片数量为 1
PUT 索引名称/_settings
{
"index" : {
"number_of_replicas" : "1"
}
}
json
1、检查es集群节点是否存活
curl http://192.142.91.14:9200/_cat/nodes?v -uicity:j7fc03HZg3HB5NWa
2、检查es集群健康状态,查看集群的健康并显示索引状态,根据返回的结果看status和unassigned_shards结果
curl http://192.142.91.14:9200/_cluster/health?level=indices -uicity:j7fc03HZg3HB5NWa
3、查看集群中每个节点的分片分配情况,如果有UNASSIGNED 会显示处出有多少个UNASSIGNED的数量
curl -XGET http://192.142.91.14:9200/_cat/allocation?v -uicity:j7fc03HZg3HB5NWa
4、查看unassigned 的原因,返回值中有"allocate_explanation":"cannot allocate because allocation is not permitted to any of the nodes" 报错
curl http://192.142.91.14:9200/_cluster/allocation/explain -uicity:j7fc03HZg3HB5NWa
主分片1,副本分片3 ,但是总节点3 ,看上去很不合理的,因为总shard数得是节点的整数倍。细致分析下 es的主副分片 不可能再同一node节点上,这样就出现了不能分配的原因(主分片的副本数+1要少于或等于节点数 R+1<=N(节点数))
5、查看索引的分片规划。
curl http://192.142.91.14:9200/_cat/shards?h=index,shard,prirep,state,unassigned.reason -uicity:j7fc03HZg3HB5NWa
unidom_prewarn_data 1 r STARTED
unidom_prewarn_data 1 r STARTED
unidom_prewarn_data 1 p STARTED
unidom_prewarn_data 1 r UNASSIGNED INDEX_CREATED
unidom_prewarn_data 2 r STARTED
unidom_prewarn_data 2 p STARTED
unidom_prewarn_data 2 r STARTED
unidom_prewarn_data 2 r UNASSIGNED INDEX_CREATED
unidom_prewarn_data 0 r STARTED
unidom_prewarn_data 0 p STARTED
unidom_prewarn_data 0 r STARTED
unidom_prewarn_data 0 r UNASSIGNED INDEX_CREATED
unidom_suggest_data 1 r STARTED
unidom_suggest_data 1 p STARTED
unidom_suggest_data 1 r STARTED
unidom_suggest_data 1 r UNASSIGNED INDEX_CREATED
unidom_suggest_data 2 r STARTED
unidom_suggest_data 2 r STARTED
unidom_suggest_data 2 p STARTED
unidom_suggest_data 2 r UNASSIGNED INDEX_CREATED
unidom_suggest_data 0 r STARTED
unidom_suggest_data 0 p STARTED
unidom_suggest_data 0 r STARTED
unidom_suggest_data 0 r UNASSIGNED INDEX_CREATED
以上的0,1,2,3,4代表节点的编号,很清楚的能看到每个节点,一个p,3个r,然后有一个不能分配
详情处理方法查看如下两个csdn
curl -XPUT 'http://192.142.91.14:9200/unidom_suggest_data(有unassigned的分片)/_settings' -H 'Content-Type: application/json' -d '{ "number_of_replicas": 2(修改分片数)}'
执行完上述命令后再次执行以下命令,查看集群状态是否成为green
curl http://192.142.91.14:9200/_cluster/health?level=indices -uicity:j7fc03HZg3HB5NWa
https://blog.csdn.net/q1035331653/article/details/122818769
es-6.8.13修改密码
yaml
(注意每台es机器相同的密码hash之后的密钥都是不同的,因此该文件不能复用,每台机器都需要执行)
背景: https://blog.csdn.net/xm393392625/article/details/130092826
使用es-6.8.13rpm包安装es之后,使用认证的方法查看es集群时
curl http://192.168.8.67:9200/_cat/nodes?v -uadmin:es6sg@asdftgb
报错Search Guard not initialized (SG11). See http://docs.search-guard.com/v6/sgadmin
处理方法:
1、首先确保elasticsearch.yml中
network.host: 0.0.0.0
2、切换到elasticsearch用户
su elasticsearch
3、修改密码
cd /export/server/elasticsearch-6.8.13/plugins/search-guard-6/tools
./hash.sh -p 新密码 会产生出一段密钥
4、复制hash出来的密钥
cd /export/server/elasticsearch-6.8.13/plugins/search-guard-6/sgconfig
vim sg_internal_users.yml (注意每台es机器相同的密码hash之后的密钥都是不同的,因此该文件不能复用,每台机器都需要执行)
#password is: j7fc03HZg3HB5NWa
admin:
readonly: true
#hash: $2y$12$aUHp2s/6kC9MIwIzRlyTROJJC7a1ew4ZOgyxps/SSb6C2XcYDCHuO(旧的hash值)
hash: $2y$12$RPIUUgNPFIVjt/CyBkVDVOYWSlut1t2F7DuiQIVvExjttFBi4n90O(第三步生成的hash值复制在这里)
roles:
- admin
attributes:
#no dots allowed in attribute names
attribute1: value1
attribute2: value2
attribute3: value3
5、执行tools/目录下的install_demo_configuration.sh脚本
sh install_demo_configuration.sh
有三步,分别输入y即可
6、执行sgadmin.sh脚本 看到success字样即完成密码修改(前提是es集群已处于运行中)
cd /export/server/elasticsearch-6.8.13/plugins/search-guard-6/tools
./sgadmin.sh -cd ../sgconfig -key ../../../config/kirk.key -cert ../../../config/kirk.pem -cacert ../../../config/root-ca.pem -nhnv -icl
es配置慢日志
yaml
官方参考文档:https://www.elastic.co/guide/en/elasticsearch/reference/7.9/index-modules-slowlog.html(注意选择对应es版本)
线上集群经常会遇到读、写性能问题,比如:cpu 被打满了、jvm heap 使用率特别高等。这些性能问题都有可能是由某一个大查询导致,给索引配上慢日志,可帮助捕获耗时较长的查询语句,有利于定位性能问题。
需要通过es api配置查询和写入的慢日志级别和阈值。当查询或者写入超过阈值时,es会打印慢日志。说明耗时和具体查询语句内容。
公有云 es 默认不支持慢日志,若用户需要,可动态配置,配置方法如下:
# 配置慢日志的阈值,可根据业务实际需求调整,若打印的慢日志太多,可适当调大阈值
# 索引设置示例
curl -XPUT http://localhost:9200/索引name/_settings
{
"index.search.slowlog.threshold.query.info": "1s",
"index.search.slowlog.threshold.fetch.info": "1s",
"index.indexing.slowlog.threshold.index.info":"2s"
}
# 对于后续新建索引,需在索引模板中设置,以匹配所有指定索引前缀的新建索引
curl -XPUT http://localhost:9200/_template/default_slowlog
{
"order": 1000,
"index_patterns": [
"索引前缀*"
],
"settings": {
"index.search.slowlog.threshold.query.info": "1s",
"index.search.slowlog.threshold.fetch.info": "1s",
"index.indexing.slowlog.threshold.index.info":"2s"
},
"mappings": { },
"aliases": { }
}
# 查看设置
curl -XGET http://localhost:9200/索引名称/_settings?pretty
ES集群读写性能优化
以下集群性能优化方案为参考方案,需根据集群具体情况具体分析:
写性能优化:
1、公有云 es 增加专有 master 节点和 client 节点
yaml
- es 节点应该角色划分,各司其责,线上集群设置专有 master 节点和 coordinate 节点,集群稳定性、安全性和读写性能均会有大大提升
- 问题一:
云 es 集群增加专有 master 节点(默认 3 个),需要重启集群,期间集群不可用(一般持续时间几分钟,若集群数据量较大,持续时间会更长),若业务侧可先停止读、写流量,恢复速度会加快。
- 问题二:
云 es 集群增加专有 coordinate 节点(建议最少 3 个),集群访问入口节点会由 data 节点变为 coordinate 节点,原 data 节点会禁止访问(业务侧不要开启 sniff 嗅探 功能),若业务侧使用 tcp 协议访问集群,业务侧需要变更集群访问节点 tcp 域名配置。若业务侧使用 http 协议访问集群,使用 LB 域名,则业务侧不需变更配置,但在 LB 域名更换绑定 ip 时,可能会有秒级网络抖动。
2、公有云 es 高级配置调优示例
yaml
修改集群高级配置,需要重启集群,支持滚动重启和强制重启两种方式:
- 集群滚动重启时,要求集群中的索引至少都有1副本,若索引为0副本,在重启过程中,该索引会red,不可用!!!
- 集群滚动重启时,一个节点重启后,等待集群恢复成健康状态 green,再重启下一个节点,重启时间较长,与数据量的大小相关
- 集群滚动重启过程中,若希望可以加快集群恢复速度,可参考:[加快索引recovery速度]
- 集群强制重启时,是所有节点同时进行重启,重启过程集群会不可用,请谨慎评估!!!

3、indices.fielddata.cache.size 优化
yaml
官方参考文档( clear cache )https://www.elastic.co/guide/en/elasticsearch/reference/6.8/indices-clearcache.html
官方参考文档( _id field )https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-id-field.html
官方参考文档( fielddata )https://www.elastic.co/guide/en/elasticsearch/reference/6.8/fielddata.html
# 查看 fielddata 缓存占用
curl -XGET http://localhost:9200/_cat/fielddata?v
# 手动清除 fielddata 缓存
curl -XPOST http://localhost:9200/test/_cache/clear?fielddata=true
curl -XPOST http://localhost:9200/*/_cache/clear?fielddata=true
yaml
fielddata 缓存大小是由 indices.fielddata.cache.size,该参数默认值为 100%,即 fielddata 缓存最大能将可使用的 jvm heap 内存大小打满,京东云控制台上提供了高级配置接口,来修改这个参数:
注意: 建议将该参数的值设置为 10%,修改该参数,需要滚动重启es集群,请注意。

4、indices.memory.index_buffer_size优化
yaml
1、过多的 segment 文件会导致频繁的 merge 操作,merge 操作会占用大量的 cpu、io 资源
2、调大 index buffer,默认为 jvm heap 大小的 10%,调大该值,线上集群建议设置为20%,可提升集群写入性能。
3、注意:调整该参数,需要滚动重启集群后,才可生效
修改示例:
# elasticsearch.yml静态配置参数,需重启节点以生效
indices.memory.index_buffer_size: 20%
5、thread_pool.write.queue_size 优化
yaml
es集群7.x之前版本,write queue 默认值为 200,当集群节点整体cpu使用率并未打满,但出现write reject 时,可通过调大write queue 值来进行优化集群的写入性能。
6、公有云 es 提升硬件配置
yaml
- 公有云 es 节点变更配置
- 提升内存配置,给更多的 filesystem cache 内存
- 提升 cpu 配置,cpu 核数越多,机器性能越好
- 若读、写流量比较大,建议使用本地盘存储,云盘存储 io 带宽有限制
7、定时清理过期索引、数据,减轻集群压力
yaml
- 集群中过多的索引数、过多的分片数、过多的数据量,会占用节点较多 jvm heap 资源(segment memory),增大 master 节点压力,降低集群整体性能
- 建议定时清理过期索引、数据
8、调大 refresh_interval 的值(牺牲实时性)
yaml
- 过多的 segment 文件会导致频繁的 merge 操作,merge 操作会占用大量的 cpu、io 资源
- 索引级别设置 refresh_interval,默认为 1s,可以调大该参数,比如 30s,这样可以减少生成的 segment 文件数量,提升写入性能,当然对查询性能提升也有帮助
- 注意:调大 refresh_interval 值,会牺牲查询的实时性,refresh_interval 值默认为 1s,意味着数据写入1s后即可查询到,假如调大到 30s,写入30s后才可查询到。适用于对查询实时性要求不高的场景
yaml
配置示例:
# 索引模板中配置refresh_interval
PUT _template/test-template
{
"order" : 0,
"index_patterns" : [
"test*"
],
"settings" : {
"index" : {
"refresh_interval" : "30s"
}
},
"mappings" : { },
"aliases" : { }
}
# 索引中配置refresh_interval,默认是1s
PUT 索引名称/_settings
{
"index.refresh_interval": "30s"
}
9、优化 translog,降低写磁盘的频率(牺牲可靠性)
yaml
对 translog 文件刷盘的优化,主要涉及到如下三个配置:
- index.translog.durability
为了保证数据写入的可靠性,该值的默认参数值为 request,即,每一次 bulk、index、delete 请求都会执行 translog 的刷盘,会较大地影响整体入库性能。如果在对入库性能要求较高的场景,并且系统可以接受一定几率的数据丢失,可以将该参数设置成 "async" 方式,并适当增加 translog 的刷盘周期。
- index.translog.sync_interval
将刷盘方式改成"async"后,es 默认每5秒执行一次translog文件的刷盘,这样会减少频繁的translog刷盘操作,提升集群的写入性能。同时存在数据丢失的风险,极端情况下会丢失5s内的数据。若追求数据写入性能,而允许部分数据的丢失,可以适当调大该值。
- index.translog.flush_threshod_size
触发es节点flush操作的条件有两个,每隔30分钟会自动执行flush操作或者当translog文件大小超过512mb后,会触发flush操作,为减少flush操作频率以提升写入性能,可通过index.translog.flush_threshod_size参数适当调大translog文件的限制大小。
index.translog.durability: async
# 注意:当索引处于open状态时,该配置有些es版本不支持动态设置
index.translog.sync_interval: 60s
index.translog.flush_threshod_size: 512mb
配置示例:
yaml
PUT 索引名称/_settings
{
"index.translog.durability": "async",
"index.translog.sync_interval": "5s",
"index.translog.flush_threshod_size": "512mb"
}
# 设置索引模板
PUT _template/索引模板名称
{
"order" : 0,
"index_patterns" : [
"*"
],
"settings" : {
"index" : {
"refresh_interval": "1m",
"translog.durability": "async",
"translog.sync_interval": "10s",
"translog.flush_threshold_size": "1g"
}
},
"mappings" : {}
}
10、均衡分片、避免热点
yaml
现象:
集群中各节点压力不均衡,比如部分节点磁盘使用率很高、cpu使用率很高,这一般与集群中数据的分布不均匀有关,部分节点压力过大,导致集群整体性能变差。
yaml
原因:
es集群采用点对点通信,符合"木桶理论",一个节点出现性能问题,往往会影响到整个集群的性能。很多情况下出现节点数据不均衡或者个别节点cpu过高的情况,会导致热点问题的产生。
yaml
热点判断:
- 1、理论上,如果es节点热点数据分布比较均衡,对应的各节点的压力也应该比较均衡,当出现各节点压力均衡时,首先应该考虑到是否有热点数据分布不均导致
- 2、查看索引分片设置(GET _cat/indices/索引名称?v),若索引分片数不为集群data节点数的倍数,则会导致索引分片无法均匀分布到每个节点上
- 3、查看索引分片数据量、分片数是否一致(GET *cat/shards/索引名称?v),*理论上同一索引各分片的数据量、文档数应该一致或差别不大,若同一索引各分片数据量、文档数相差较大,多为业务写入数据时指定了路由规则导致(需业务侧确认)
- 4、查看索引主分片分布是否均匀,es写入是往主分片中写的,然后再同步数据到副本分片,若索引主分片分布不均匀,会导致热点问题
yaml
优化:
- 合理设置主分片数,确保单个索引的分片可以均匀分配在所有数据节点上。线上集群一般建议索引数较大的索引"主分片数量设置成data节点数量或者data节点数量的倍数"
- 当集群发生重启,或者扩容时,很容易导致原来均匀分布的索引变得不均匀。index.routing.allocation.total_share_per_node:限定每个索引在每个节点上可分配的主分片数
yaml
示例:
# 假如 5个节点的集群。索引有 5个主分片,1个副本,应该如何设置 index.routing.allocation.total_share_per_node 的值,以强制让数据分布均匀?理论值:(5+5)/5 = 2
# 情况1:假如只是临时设置该参数,强制均衡一下分片,可按理论值设置,索引分片强制均衡完成后,再重新取消该限制
# 情况2:假如想将该参数设置到索引模板中,对索引一直持续生效,生产环境中建议要适当调大这个数字,避免有节点下线时,分片无法正常迁移
PUT 索引名称/_settings
{
"index" : {
"routing" : {
"allocation" : {
"total_shards_per_node" : 2
}
}
}
}
yaml
避免使用自定义路由:
如果使用自定义路由,可能会导致同一索引每个分片之间的数据量差异较大。es默认路由字段为 _id
11、write reject 问题优化
yaml
- 集群整体cpu使用率均非常高,导致 write reject,计算资源已经到达瓶颈,可扩容集群解决
- 集群只有部分节点cpu使用率非常高,导致 write reject,首先排查 "9、均衡分片、避免热点"
- 集群整体cpu使用率并不高,确存在较多 write reject,可考虑调大write queue,默认为 200
- 参照前面几条优化方案,提升集群整体性能
12、频繁gc问题优化
yaml
默认young 区较小,若集群节点young gc频繁,或产生 old gc,建议优化:
- 1、索引配置慢日志,根据捕获到的慢日志信息,优化业务请求
- 2、更换jvm 垃圾回收器,建议可更换为g1
读性能优化:
1、优化写入性能
yaml
同一集群的读、写是共用资源的,优化写入性能的方法同样适用于优化读性能,彼此互相影响,相辅相成。
2、优化分片
yaml
- 避免 Over Sharing
一个查询需要访问每一个分片,分片过多,会导致不必要的查询开销
- 结合应用场景,控制单个分片的尺寸
Search: 20GB
Logging: 40GB
- Force-merge Read-only索引
使用基于时间序列的索引,将只读的索引进行 force merge,减少 segment 数量
3、增加协调节点数量
4、减少集群中的索引数量和分片数量
5、search reject 问题优化
yaml
搜索线程池显示"拒绝"计数的持续增加,该计数基于上次集群重启而累积
curl -XGET http://localhost:9200/_cat/thread_pool?v
curl -XGET http://localhost:9200/_cat/thread_pool/search?v&&h=node_name,name,active,queue,rejected,completed
yaml
问题描述:
场景1: 查询的目标是太多分片,超过集群中的CPU核数。这会在搜索线程池中创建排队任务,从而导致搜索拒绝。(假如一个索引有100个分片,极端情况这100个分片都在一个node上,当有查询请求打过来时,节点会分别向着100个分片发送100个请求来进行搜索,100个请求就需要100个线程来处理,如果cpu核数只有20,则一次只能处理20个请求,那么就会造成任务的堆积。)
- 场景2: 磁盘 I/O 读写速度慢
- 场景3: cpu 繁忙导致搜索排队(写入占用大量 cpu 资源)
- 场景4: search_queue 较小,将search_queue适当调大,就算cpu处理不过来,也不会reject,而是在 search queue中进行排队
- 场景5: 查询语句复杂,需要大量计算资源,单次查询比较耗时
yaml
解决方案:
- 减少索引分片数,创建索引时(索引数据量不大)设置1主1副(7.x版本后默认1主1副)
- 改进磁盘I/O性能,使用SSD磁盘,做raid
- 提升cpu配置,或者扩容以分摊压力
- cpu使用率尚未达到瓶颈,可调大search_queue,"thread_pool.search.queue_size: 1000"
- 优化查询语句,避免复杂大查询
6、增加 replica 副本数量(特殊情况下)
yaml
- 资源充足情况下可考虑(cpu,memory,disk,带宽等资源有较大空闲)
- 对安全性要求特别高时可考虑多副本
- 增加 replica 副本数量,会降低写入性能
7、集群侧限制业务大查询
8、提升硬件配置
yaml
- 更多 cpu 核数
- 更大 file cache 内存
- 更高配置硬盘,固态硬盘(SSD)性能比机械硬盘(HDD)更好,硬盘做raid,raid 0,raid 5,raid 10,提升磁盘读写性能
9、避免使用 script 脚本
yaml
尽量将数据先行计算,然后保存到 Elasticsearch 中,尽量避免查询时的 Script 计算
10、避免使用通配符开始的正则表达
yaml
通配符开头的正则,性能非常糟糕,需避免使用
错误示例:
yaml
GET test/_search
{
"query": {
"wildcard": {
"title": {
"value": "*elastic*"
}
}
}
}
11、避免复杂的聚合查询
12、避免过深的分页查询
13、避免使用 Nested 类型的数据,避免使用 Parent/Child 关系
yaml
- 使用 Nested 类型的数据,查询速度会慢几倍
- 使用 Parent/Child 关系,查询速度会慢几百倍
索引分片数怎么设置,设置不合理会导致数据分布不均
yaml
数据分布不均衡的问题一般是由于索引的分片数设置与集群中的数据节点数不一致导致的,索引分片数设置方式:详见第7条
建议:
集群n个data节点,索引的分片数设置就为n主1副或者n*m(m不为0)主1副,好比3个数据节点,索引分片数可以设置为3主1副或者6主1副等等;假设集群3个data节点,索引设置的1主1副,索引个数达到一定量以后,集群的水位分布不均衡问题就会很明显
ES分片迁移
分片(Shard)是 ES 水平扩展与并发读写 的基本单位。理解分片迁移机制,是运维 rebalance、扩缩容、节点替换的基础。
分片迁移触发与流程
#mermaid-svg-WaWqjqZz0W4SXzYk{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-WaWqjqZz0W4SXzYk .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-WaWqjqZz0W4SXzYk .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-WaWqjqZz0W4SXzYk .error-icon{fill:#552222;}#mermaid-svg-WaWqjqZz0W4SXzYk .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-WaWqjqZz0W4SXzYk .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-WaWqjqZz0W4SXzYk .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-WaWqjqZz0W4SXzYk .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-WaWqjqZz0W4SXzYk .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-WaWqjqZz0W4SXzYk .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-WaWqjqZz0W4SXzYk .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-WaWqjqZz0W4SXzYk .marker{fill:#333333;stroke:#333333;}#mermaid-svg-WaWqjqZz0W4SXzYk .marker.cross{stroke:#333333;}#mermaid-svg-WaWqjqZz0W4SXzYk svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-WaWqjqZz0W4SXzYk p{margin:0;}#mermaid-svg-WaWqjqZz0W4SXzYk .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-WaWqjqZz0W4SXzYk .cluster-label text{fill:#333;}#mermaid-svg-WaWqjqZz0W4SXzYk .cluster-label span{color:#333;}#mermaid-svg-WaWqjqZz0W4SXzYk .cluster-label span p{background-color:transparent;}#mermaid-svg-WaWqjqZz0W4SXzYk .label text,#mermaid-svg-WaWqjqZz0W4SXzYk span{fill:#333;color:#333;}#mermaid-svg-WaWqjqZz0W4SXzYk .node rect,#mermaid-svg-WaWqjqZz0W4SXzYk .node circle,#mermaid-svg-WaWqjqZz0W4SXzYk .node ellipse,#mermaid-svg-WaWqjqZz0W4SXzYk .node polygon,#mermaid-svg-WaWqjqZz0W4SXzYk .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-WaWqjqZz0W4SXzYk .rough-node .label text,#mermaid-svg-WaWqjqZz0W4SXzYk .node .label text,#mermaid-svg-WaWqjqZz0W4SXzYk .image-shape .label,#mermaid-svg-WaWqjqZz0W4SXzYk .icon-shape .label{text-anchor:middle;}#mermaid-svg-WaWqjqZz0W4SXzYk .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-WaWqjqZz0W4SXzYk .rough-node .label,#mermaid-svg-WaWqjqZz0W4SXzYk .node .label,#mermaid-svg-WaWqjqZz0W4SXzYk .image-shape .label,#mermaid-svg-WaWqjqZz0W4SXzYk .icon-shape .label{text-align:center;}#mermaid-svg-WaWqjqZz0W4SXzYk .node.clickable{cursor:pointer;}#mermaid-svg-WaWqjqZz0W4SXzYk .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-WaWqjqZz0W4SXzYk .arrowheadPath{fill:#333333;}#mermaid-svg-WaWqjqZz0W4SXzYk .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-WaWqjqZz0W4SXzYk .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-WaWqjqZz0W4SXzYk .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-WaWqjqZz0W4SXzYk .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-WaWqjqZz0W4SXzYk .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-WaWqjqZz0W4SXzYk .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-WaWqjqZz0W4SXzYk .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-WaWqjqZz0W4SXzYk .cluster text{fill:#333;}#mermaid-svg-WaWqjqZz0W4SXzYk .cluster span{color:#333;}#mermaid-svg-WaWqjqZz0W4SXzYk div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-WaWqjqZz0W4SXzYk .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-WaWqjqZz0W4SXzYk rect.text{fill:none;stroke-width:0;}#mermaid-svg-WaWqjqZz0W4SXzYk .icon-shape,#mermaid-svg-WaWqjqZz0W4SXzYk .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-WaWqjqZz0W4SXzYk .icon-shape p,#mermaid-svg-WaWqjqZz0W4SXzYk .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-WaWqjqZz0W4SXzYk .icon-shape .label rect,#mermaid-svg-WaWqjqZz0W4SXzYk .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-WaWqjqZz0W4SXzYk .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-WaWqjqZz0W4SXzYk .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-WaWqjqZz0W4SXzYk :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 触发条件
新建/删除索引
节点上下线
节点重启
磁盘水位 rebalance
手动 reroute
allocation filter include/exclude
Master 重新计算路由表
Recovery 过程
INIT → 从源分片拷贝 segment
TRANSLOG 重放增量
STARTED → 对外服务
yaml
分片(shard)存储了一个索引的部分数据,多个分片组成一个完整的索引。分片的形式提升了一个索引查询和写入的并发能力,以横向的方式提升了集群数据存储的上限。比如一个索引1000G,但是集群内最大的数据节点的磁盘容量是500G,在没有分片的情况下,这个索引是无法写入到这个集群的。将这个索引拆分成2个分片理论上两个同样配置的节点就可以存储这个索引所有的数据。 分片这种结构在合理的设置下突破物理硬件的上限,综合利用硬件群集的能力。
yaml
迁移: 根据集群的分配策略,分片在集群内会出现从一个节点移动到另一个节点的情况。而一下几种情况都会触发这种迁移的发生。
•新建或删除索引
•集群节点变动: 新增、减少
•节点重启
•手动reroute
yaml
分片的迁移是需要消耗集群内部带宽、cpu、磁盘、内存资源的,实际集群维护过程中有时需要人工干预分片迁移的进度、修复迁移失败的分片。
1、查看分片迁移的状态
curl -XGET http://192.168.56.131:9200/_cat/recovery?v&&active_only=true
2、如果有分配失败的分片,查看失败的原因
curl -XGET http://192.168.56.131:9200/_cluster/allocation/explain?pretty
注意: 鉴于分片的迁移需要消耗集群的资源,对于所有主动触发的分片迁移, 例如: 重启、扩缩容等操作建议放在业务低峰期进行。分片迁移过程中可以调整并发的分片数和分片恢复的速度上限以缩短集群恢复时间。
对于非主动触发的分片迁移,如果对业务产生影响,可以通过命令控制分片恢复的速度,减少对业务的影响
1、调整分片并发和速度
curl -XPUT http://192.168.56.131:9200/_cluster/settings
{
"persistent": {
"cluster.routing.allocation.node_concurrent_recoveries": 2,
"indices.recovery.max_bytes_per_sec": "40mb/s"
}
}
详解:
cluster.routing.allocation.node_concurrent_recoveries 分片恢复的并发进程数
indices.recovery.max_bytes_per_sec 索引恢复时带宽上限
使用上面的命令根据需要调大或调小集群分片恢复的并发数和带宽上限。以控制集群恢复的时间和对业务影响的程度。
分片的自动迁移
yaml
以下情况会触发分片的自动迁移:
•新建或删除索引
•集群节点变动:新增、减少
•节点重启
手动迁移分片
yaml
分片主动迁移es提供api实现人为主动操作分片在节点上的分配
curl -XPOST http://192.68.57.32:9200/_cluster/reroute
request样例
curl -XPOST http://192.68.57.32:9200/_cluster/reroute?metric=none
命令可接受的参数
dry_run 请求中加上dry_run参数后,这个请求只会根据当前集群状态计算命令执行的结果并返回它,并不会在集群上真正执行.
curl -XPOST http://192.68.57.32:9200/_cluster/reroute?dry_run
metric 指定命令返回的内容
curl -XPOST http://192.68.57.32:9200/_cluster/reroute?metric=master_node
可指定的模块:
master_node #显示主节点部分
metadata #显示元数据部分
node #显示节点部分
routing_table #显示路由表部分
version #显示版本信息
retry_failed 重试分配失败的分片
curl -XPOST http://192.68.57.32:9200/_cluster/reroute?retry_failed=true
master_timeout 主节点超时时间
timeout 命令超时时间
请求体内容
样例:
curl -XPOST http://192.68.57.32:9200/_cluster/reroute?metric=none
{
"commands": [
{
"move": {
"index": "test", "shard": 0,
"from_node": "node1", "to_node": "node2"
}
},
{
"allocate_replica": {
"index": "test", "shard": 1,
"node": "node3"
}
}
]
}
_cluster/reroute 支持的post方法的请求,请求体内需要提供commands参数。 commands需要提供一个列表,指定要操作的内容。
commands可接受的子命令:
move、cancel、allocate_replica、allocate_stale_primary、allocate_empty_primary。
样例:
move 将一个分片从一个节点移动到另外一个节点
POST /_cluster/reroute
{
"commands": [
{
"move": {
"index": "test", #索引名
"shard": 0, #分片编号
"from_node": "node1", #分片源节点
"to_node": "node2" #分片迁移目标节点
}
}
]
}
cancel 撤销一个分片的分配,默认操作对象为副本分片。
执行后可以强制重新初始化副本分片并从主分片同步数据。如果确认需要操作主分片,需要在请求主体中增加allow_primary参数并置为true.
#未验证
POST /_cluster/reroute
{
"commands": [
{
"cancel": {
"index": "test", #索引名
"shard": 0, #分片编号
"node": "node1" #分片源节点
}
}
]
}
allocate_replica 分配一个未分配的分片到指定节点
POST /_cluster/reroute?metric=none
{
"commands": [
{
"allocate_replica": {
"index": "test", #索引名
"shard": 1, #分配编号
"node": "node3" #分片分配的节点
}
}
]
}
allocate_stale_primary 将一个保留有过期数据的副本分片提升为主节点
POST /_cluster/reroute
{
"commands": [
{
"allocate_stale_primary": {
"index": "test", #索引名
"shard": 0, #分片编号
"node": "node1" #分片源节点
"accept_data_loss": "true" #接受潜在的数据丢失
}
}
]
}
accept_data_loss #执行这条命令后,如果一个持有最新副本(good copy)的节点重新加入当前集群,新节点上的最新副本(good copy)会被分配的过期副本(stale copy)上的数据所覆盖。为了确保执行命令时了解到这条命令的风险,增加将accept_data_loss设置为true
allocate_empty_primary 分配一个空分片到指定节点
POST /_cluster/reroute
{
"commands": [
{
"allocate_stale_primary": {
"index": "test", #索引名
"shard": 0, #分片编号
"node": "node1" #分片源节点
"accept_data_loss": "true" #接受潜在的数据丢失
}
}
]
}
accept_data_loss #请求中值设置为true. 这条命令的执行将会导致分配的这个主分片原来的数据全部丢失。如果后续有一个节点重新加入集群,且这个节点上有执行分片的数据,新节点上的这个分片数据将会被删除。
注意:
allocate_stale_primary、allocate_empty_primary这两条命令操作对象都是主分片,有一定丢失数据的风险。
一般情况下主分片的分配都会由es集群自动处理完成,只有在极端情况下才需要使用下面两条命令。
造成主分片分配失败的原因:
•新索引创建但是集群内node都不满足分配策略导致主分片无法分配,主分片处理未分配状态。
•当前集群内数据节点上找不到数据的最新副本分片,为防止数据丢失,系统不会将过期副本分片提升为主分片,主分片处理未分配状态。
一般用于在原始数据无法恢复,并且可以接受数据丢失的情况下。 如果是遇到临时可修复的问题,不要使用这两条命令,使用上面提到的retry_failed来修复分片的分配。
注意一旦执行了这两条命令,当有一个新的节点加入当前集群后,如果新节点上带有这个分片的副本,那么新节点上的副本将会被删除或覆盖。
手动迁移分片场景
yaml
各个节点上分片数一致,但因为不同的索引大小不一,导致个别节点磁盘使用率超90%,其他节点在50%左右。这种情况下一旦发生节点重启,90%磁盘使用率的节点可能会被打满?
解决:
这种场景下,只能是手动将快写满的节点上的分片迁移到其他节点。
手动迁移任意一个分片都会触发集群的自动平衡,以恢复集群到平衡状态。比如,从node1上迁移一个分片到node2上之后,动态平衡会从node2再迁移一个分片到node1。可以通过配置cluster.routing.rebalance.enable参数,禁用动态平衡以维持手动迁移分片的结果。
禁用自动平衡(支持索引级别配置)
PUT /_cluster/settings
{
"transient" : {
"cluster.routing.rebalance.enable" : "none"
}
}
手动将分片从磁盘使用率超90%的节点上将分片移走
POST /_cluster/reroute
{
"commands": [
{
"move": {
"index": "test", #索引名
"shard": 0, #分片编号
"from_node": "node1", #分片源节点
"to_node": "node2" #分片迁移目标节点
}
}
]
}
解决索引及分片问题后恢复集群自动平衡
PUT /_cluster/settings
{
"transient" : {
"cluster.routing.rebalance.enable" : "all"
}
}
?metric=none
{
"commands": [
{
"allocate_replica": {
"index": "test", #索引名
"shard": 1, #分配编号
"node": "node3" #分片分配的节点
}
}
]
}
allocate_stale_primary 将一个保留有过期数据的副本分片提升为主节点
POST /_cluster/reroute
{
"commands": [
{
"allocate_stale_primary": {
"index": "test", #索引名
"shard": 0, #分片编号
"node": "node1" #分片源节点
"accept_data_loss": "true" #接受潜在的数据丢失
}
}
]
}
accept_data_loss #执行这条命令后,如果一个持有最新副本(good copy)的节点重新加入当前集群,新节点上的最新副本(good copy)会被分配的过期副本(stale copy)上的数据所覆盖。为了确保执行命令时了解到这条命令的风险,增加将accept_data_loss设置为true
allocate_empty_primary 分配一个空分片到指定节点
POST /_cluster/reroute
{
"commands": [
{
"allocate_stale_primary": {
"index": "test", #索引名
"shard": 0, #分片编号
"node": "node1" #分片源节点
"accept_data_loss": "true" #接受潜在的数据丢失
}
}
]
}
accept_data_loss #请求中值设置为true. 这条命令的执行将会导致分配的这个主分片原来的数据全部丢失。如果后续有一个节点重新加入集群,且这个节点上有执行分片的数据,新节点上的这个分片数据将会被删除。
注意:
allocate_stale_primary、allocate_empty_primary这两条命令操作对象都是主分片,有一定丢失数据的风险。
一般情况下主分片的分配都会由es集群自动处理完成,只有在极端情况下才需要使用下面两条命令。
造成主分片分配失败的原因:
•新索引创建但是集群内node都不满足分配策略导致主分片无法分配,主分片处理未分配状态。
•当前集群内数据节点上找不到数据的最新副本分片,为防止数据丢失,系统不会将过期副本分片提升为主分片,主分片处理未分配状态。
一般用于在原始数据无法恢复,并且可以接受数据丢失的情况下。 如果是遇到临时可修复的问题,不要使用这两条命令,使用上面提到的retry_failed来修复分片的分配。
注意一旦执行了这两条命令,当有一个新的节点加入当前集群后,如果新节点上带有这个分片的副本,那么新节点上的副本将会被删除或覆盖。
### 手动迁移分片场景
```yaml
各个节点上分片数一致,但因为不同的索引大小不一,导致个别节点磁盘使用率超90%,其他节点在50%左右。这种情况下一旦发生节点重启,90%磁盘使用率的节点可能会被打满?
解决:
这种场景下,只能是手动将快写满的节点上的分片迁移到其他节点。
手动迁移任意一个分片都会触发集群的自动平衡,以恢复集群到平衡状态。比如,从node1上迁移一个分片到node2上之后,动态平衡会从node2再迁移一个分片到node1。可以通过配置cluster.routing.rebalance.enable参数,禁用动态平衡以维持手动迁移分片的结果。
禁用自动平衡(支持索引级别配置)
PUT /_cluster/settings
{
"transient" : {
"cluster.routing.rebalance.enable" : "none"
}
}
手动将分片从磁盘使用率超90%的节点上将分片移走
POST /_cluster/reroute
{
"commands": [
{
"move": {
"index": "test", #索引名
"shard": 0, #分片编号
"from_node": "node1", #分片源节点
"to_node": "node2" #分片迁移目标节点
}
}
]
}
解决索引及分片问题后恢复集群自动平衡
PUT /_cluster/settings
{
"transient" : {
"cluster.routing.rebalance.enable" : "all"
}
}