ELK Stack 面试题
35 道题- 分类
- 可观测性
- 子分类
- logs
- 题目数
- 35 道
1 ELK Stack 由哪些核心组件组成?各组件职责是什么?
答案:
ELK Stack 是 Elastic 公司推出的日志管理与分析平台,由 Elasticsearch、Logstash、Kibana 三大核心组件构成。
| 组件 | 职责 | 关键能力 |
|---|---|---|
| Elasticsearch | 分布式搜索与分析引擎 | 数据存储、全文检索、聚合分析、RESTful API |
| Logstash | 服务端数据处理管道 | 多源采集、数据解析、过滤转换、多端输出 |
| Kibana | 数据可视化与管理平台 | 仪表盘、数据探索、告警管理、集群管理 |
扩展组件:
- Beats(Filebeat/Metricbeat/Winlogbeat):轻量级数据采集器,替代 Logstash 采集层
- Elastic Agent:统一代理,整合 Beats + Endpoint Security
- APM Server:应用性能监控数据接入
数据流:
数据源 → Beats/Logstash → Elasticsearch → Kibana
↕
集群管理 / ILM / 快照
2 Elasticsearch 集群中 Master、Data、Coordinating 和 Ingest 节点的职责分别是什么?
答案:
Elasticsearch 采用逻辑节点角色分离架构,支持多角色混合部署。
| 节点角色 | 核心职责 | 关键配置 |
|---|---|---|
| Master | 集群元数据管理、索引创建删除、节点上下线 | node.roles: [master],奇数台(3/5),低资源 |
| Data | 数据存储、CRUD、搜索聚合 | node.roles: [data],高 IOPS 存储,核心节点 |
| Coordinating | 请求路由分发、结果归并 | node.roles: [],CPU 密集,负载均衡器 |
| Ingest | 数据预处理管道 | node.roles: [ingest],可选独立部署 |
高可用要求:
集群规模 Master节点 Data节点 最小法定票数
1-2 1 1-2 1
3-5 3 2+ 2
6+ 3 3+ 2
最佳实践:
- Master 节点仅 3 台,不承载数据,避免 GC 影响集群稳定性
- Coordinating 节点按查询负载扩展,通常 2-4 台
- Data 节点按数据量和性能需求扩展,建议 3 副本起
3 Elasticsearch 索引、分片(Shard)和副本(Replica)的关系是什么?
答案:
Elasticsearch 的索引是逻辑命名空间,底层由分片(物理 Lucene 实例)构成。
核心概念:
| 概念 | 说明 | 默认值 |
|---|---|---|
| Index | 具有相同映射的文档集合 | — |
| Primary Shard | 索引的水平分区,每个分片是完整 Lucene 索引 | 1(7.x+),之前为 5 |
| Replica Shard | 主分片的完整副本 | 1(每主分片一个副本) |
| Shard | 分片总数 = Primaries × (1 + Replicas) | — |
分片分配算法:
shard_routing = hash(_id/routing) % number_of_primary_shards
分片规划原则:
- 主分片数在索引创建后不可修改(
_split/_shrink除外) - 单分片推荐数据量:20GB-50GB,最大不超过 100GB
- 单节点分片数建议 < 1000(总分片数 < 10000)
- 副本数可在线调整:
PUT /index/_settings {"number_of_replicas": 2}
分片与节点关系:
Nodes: 3 Primaries: 5 Replicas: 1 总分片: 10
Node A: P0 P2 P4 R1 R3
Node B: P1 P3 R0 R2 R4
Node C: R0 R1 R2 R3 R4
4 Elasticsearch 写入流程(Index / Update)从客户端到数据落盘的完整过程是怎样的?
答案:
Elasticsearch 写入流程涉及协调节点、主分片、副本分片和 Lucene 内部机制。
写入流程(Index API):
Client → Coordinating Node
│
路由到 Primary Shard
│
写入 Lucene Buffer (内存)
│
写入 Translog (磁盘)
│
[等待副本同步]
│
返回成功给 Client
│
[后台刷新 refresh_interval=1s]
│
内存 Segment 变为可搜索
│
[后台 flush]
│
Translog 落盘 + Segment 持久化
分段流程细节:
| 阶段 | 操作 | 可搜索 | 持久化 |
|---|---|---|---|
| Buffer | 写入内存缓冲区 | 否 | 否 |
| Refresh | 生成新的 Lucene Segment | 是 | 否(文件系统缓存) |
| Flush | 提交到磁盘 | 是 | 是 |
| Translog | 操作日志 | 否 | 是(故障恢复) |
Update 流程:
Client → Coordinating → Primary
1. 读取原有 _source
2. 应用修改
3. 重新索引文档(删除 + 创建)
4. 返回结果
优化参数:
PUT /_template/logging
{
"settings": {
"index.refresh_interval": "30s",
"index.translog.durability": "async",
"index.translog.sync_interval": "5s",
"index.number_of_replicas": 0,
"index.sort.field": "@timestamp",
"index.sort.order": "desc"
}
}
5 Elasticsearch 查询流程(Query then Fetch)如何工作?
答案:
Elasticsearch 搜索请求采用两阶段执行模型:Query 阶段和 Fetch 阶段。
Query 阶段:
Coordinating Node 接收搜索请求
│
广播到所有分片(主分片 + 副本分片)
│
每个分片本地执行查询,生成 Top N 结果
│
返回结果(文档 ID + 排序值)给协调节点
│
协调节点归并排序,选取全局 Top N
Fetch 阶段:
Coordinating Node 向相关分片发送 GET 请求
│
分片根据文档 ID 获取完整 _source
│
返回完整文档给协调节点
│
协调节点组装最终响应
分片选择策略(Preference):
| 参数 | 行为 | 场景 |
|---|---|---|
_primary | 仅查询主分片 | 一致性敏感场景 |
_local | 优先本节点分片 | 减少网络开销 |
custom_string | 相同值路由到同一分片 | 会话亲和性 |
搜索类型:
// query_then_fetch(默认)- 两阶段
GET /index/_search?search_type=query_then_fetch
// dfs_query_then_fetch - 增加全局词频统计
GET /index/_search?search_type=dfs_query_then_fetch
6 Elasticsearch 倒排索引(Inverted Index)的数据结构和工作原理是什么?
答案:
倒排索引是 Elasticsearch/Lucene 实现全文搜索的核心数据结构,通过"词项→文档"的映射关系实现快速检索。
正向索引 vs 倒排索引:
| 维度 | 正向索引 | 倒排索引 |
|---|---|---|
| 映射方向 | 文档 → 词项 | 词项 → 文档 |
| 查询效率 | 遍历所有文档 | 直接定位词项 |
| 存储结构 | 文档列表 | 词项字典 + 倒排列表 |
倒排索引结构:
原始文档:
Doc1: "Elasticsearch is a search engine"
Doc2: "Elasticsearch uses inverted index"
分词后:
Term DocID:Position
elasticsearch Doc1:0, Doc2:0
search Doc1:2
engine Doc1:4
uses Doc2:1
inverted Doc2:2
index Doc2:3
倒排索引存储:
Term → [DocID, Term Frequency, Positions...]
Lucene 倒排索引编码优化:
| 技术 | 说明 | 压缩效果 |
|---|---|---|
| Frame of Reference | 差值编码 + 按块打包 | 减少整数存储空间 |
| Roaring Bitmaps | 文档 ID 按位图编码 | 高效集合运算 |
| Block Tree Terms Index | 词项字典的前缀压缩 | 减少字典内存占用 |
| Stored Fields | _source 压缩存储 | LZ4 / deflate 压缩 |
倒排索引查询过程:
查询 "elasticsearch search engine"
1. 词项字典查找:elasticsearch ✓ search ✓ engine ✓
2. 取倒排列表交集:Doc1(命中 3 个词项)
3. BM25 评分计算
4. 返回排序后结果
7 Elasticsearch 的 Mapping 是什么?Dynamic Mapping 和 Explicit Mapping 有什么区别?
答案:
Mapping 定义了索引中字段的名称、数据类型、分词方式及索引策略,相当于数据库的 Schema 定义。
Mapping 类型:
| 类型 | 说明 | 适用场景 |
|---|---|---|
| Dynamic Mapping | 自动检测字段类型 | 快速接入、开发测试 |
| Explicit Mapping | 手动定义字段类型 | 生产环境、性能敏感 |
| Strict Mapping | 禁止未知字段 | 日志标准化 |
类型自动检测规则:
JSON类型 → ES 类型
字符串+日期格式 → date
字符串 → text + keyword(多字段)
整数 → long
浮点数 → float
布尔值 → boolean
对象 → object
数组 → 首个元素类型
显式 Mapping 示例:
PUT /logs-nginx
{
"mappings": {
"dynamic": "strict",
"properties": {
"@timestamp": { "type": "date" },
"message": { "type": "text" },
"level": { "type": "keyword" },
"request": {
"properties": {
"method": { "type": "keyword" },
"path": { "type": "text", "index": false },
"status": { "type": "integer" },
"latency_ms": { "type": "float" }
}
},
"host": { "type": "keyword" },
"env": { "type": "keyword", "index": false }
}
}
}
字段类型选择建议:
| 场景 | 推荐类型 | 原因 |
|---|---|---|
| 精确匹配、聚合、排序 | keyword | 不分词、低开销 |
| 全文搜索 | text | 分词、支持模糊匹配 |
| IP 地址 | ip | 支持 CIDR 范围查询 |
| 地理位置 | geo_point | 支持地理距离、多边形查询 |
| 时间戳 | date | 支持日期数学、范围聚合 |
| 日志消息(不搜索) | text + index: false | 仅存储不索引 |
| 大文本(>10KB) | text + fields.keyword | 分词搜索 + 精确匹配 |
8 Elasticsearch 的分词器(Analyzer)由哪些组件构成?如何自定义分词器?
答案:
Analyzer 是 Elasticsearch 处理文本的管道,由三个顺序组件构成:Character Filters、Tokenizer、Token Filters。
Analyzer 组成:
输入文本 → [Character Filters] → [Tokenizer] → [Token Filters] → 词项列表
↓ ↓ ↓
清理字符 切分词项 增删改词项
内置 Analyzer:
| Analyzer | 行为 | 示例(“I’m running & walking”) |
|---|---|---|
| standard | Unicode 分词 + 小写 | i’m, running, walking |
| simple | 非字母分隔 + 小写 | i, m, running, walking |
| whitespace | 空格分隔 | I’m, running, &, walking |
| keyword | 不处理,整体输出 | I’m running & walking |
| pattern | 正则分隔 | 按模式分割 |
自定义 Analyzer 示例:
PUT /logs-nginx
{
"settings": {
"analysis": {
"char_filter": {
"remove_html": {
"type": "html_strip"
}
},
"tokenizer": {
"nginx_log": {
"type": "pattern",
"pattern": "\\s+"
}
},
"filter": {
"lowercase": {
"type": "lowercase"
},
"ngram_filter": {
"type": "ngram",
"min_gram": 2,
"max_gram": 4
}
},
"analyzer": {
"custom_nginx": {
"type": "custom",
"char_filter": ["remove_html"],
"tokenizer": "nginx_log",
"filter": ["lowercase", "ngram_filter"]
}
}
}
},
"mappings": {
"properties": {
"url": {
"type": "text",
"analyzer": "custom_nginx"
}
}
}
}
常用 Token Filter:
| Filter | 功能 | 场景 |
|---|---|---|
| lowercase | 转换为小写 | 标准化 |
| stop | 移除停用词 | 提高搜索质量 |
| synonym | 同义词替换 | 搜索扩展 |
| ngram/edge_ngram | 子词切分 | 前缀搜索、建议 |
| shingle | 词元组合 | 短语匹配 |
9 Elasticsearch 的聚合(Aggregation)分为哪些类型?Bucket 和 Metric 聚合的区别是什么?
答案:
Elasticsearch 聚合框架分为三大类:Metric、Bucket 和 Pipeline 聚合,支持嵌套组合实现多维分析。
聚合分类:
| 类型 | 功能 | 示例 |
|---|---|---|
| Metric | 数值计算 | avg、sum、min、max、stats、cardinality、percentiles |
| Bucket | 文档分组 | terms、date_histogram、range、filter、geohash_grid |
| Pipeline | 聚合结果再计算 | derivative、moving_avg、cumulative_sum |
核心区别:
Metric 聚合:返回单个数值
GET /orders/_search
{
"aggs": {
"avg_price": { "avg": { "field": "price" } }
}
}
→ avg_price: 123.45
Bucket 聚合:返回分组结果(每组含文档数和嵌套聚合)
GET /logs/_search
{
"aggs": {
"by_status": {
"terms": { "field": "status" },
"aggs": {
"avg_latency": { "avg": { "field": "latency_ms" } }
}
}
}
}
→ 200: count=5000 avg_latency=120
→ 500: count=50 avg_latency=3500
date_histogram 时序聚合:
GET /logs-nginx-*/_search
{
"size": 0,
"query": {
"range": { "@timestamp": { "gte": "now-7d", "lte": "now" } }
},
"aggs": {
"requests_over_time": {
"date_histogram": {
"field": "@timestamp",
"fixed_interval": "1h",
"min_doc_count": 0,
"extended_bounds": { "min": "now-7d", "max": "now" }
},
"aggs": {
"avg_latency": { "avg": { "field": "latency_ms" } },
"p99_latency": { "percentiles": { "field": "latency_ms", "percents": [99] } }
}
}
}
}
10 Elasticsearch 的评分机制(BM25)是什么?如何影响搜索排序?
答案:
BM25(Best Matching 25)是 Elasticsearch 5.0 起默认的相似度算法,替代了 TF/IDF。
BM25 公式:
Score(D,Q) = Σ IDF(q) × TF(q,D)
IDF(q) = log(1 + (N - n(q) + 0.5) / (n(q) + 0.5))
TF(q,D) = f(q,D) × (k1 + 1) / (f(q,D) + k1 × (1 - b + b × |D| / avgdl))
| 参数 | 含义 | 默认值 | 影响 |
|---|---|---|---|
| k1 | 词频饱和度控制 | 1.2 | 越大,高频词影响力越大 |
| b | 文档长度归一化 | 0.75 | 越大,短文档越有利 |
| IDF | 逆文档频率 | — | 稀有词权重更高 |
调优示例:
PUT /logs-nginx
{
"settings": {
"index": {
"similarity": {
"custom_bm25": {
"type": "BM25",
"k1": 1.0,
"b": 0.5
}
}
}
},
"mappings": {
"properties": {
"message": {
"type": "text",
"similarity": "custom_bm25"
}
}
}
}
常见排序控制手段:
| 手段 | 方式 | 场景 |
|---|---|---|
| boosting | 查询时加权 | 提升特定字段/条件 |
| function_score | 函数评分 | 自定义评分逻辑 |
| constant_score | 忽略 TF/IDF | 只关心匹配与否 |
| sort | 字段排序 | 按时间/数值排序 |
| rescore | 第二阶段重排序 | 提升精度 |
function_score 示例:
GET /logs/_search
{
"query": {
"function_score": {
"query": { "match": { "message": "error" } },
"functions": [
{ "filter": { "term": { "level": "CRITICAL" } }, "weight": 10 },
{ "filter": { "term": { "level": "ERROR" } }, "weight": 3 },
{ "gauss": { "@timestamp": { "origin": "now", "scale": "1h" } } }
],
"score_mode": "multiply",
"boost_mode": "multiply"
}
}
}
11 Elasticsearch 集群的节点发现和选主机制(Zen Discovery / Cluster Coordination)是如何工作的?
答案:
Elasticsearch 的集群协调机制经历从 Zen Discovery 到基于 Raft 的 Cluster Coordination 的演进(7.0 起默认)。
集群协调流程:
节点启动 → 发现种子节点 → 加入集群 → 参与选主
│ │ │
seed_hosts cluster minimum_master_nodes
name (已废弃)
选主过程(Raft):
1. 投票阶段:
每个节点向候选节点投票
候选节点获得 > n/2 票成为 Master
2. 日志复制:
Master 向其他节点推送集群状态变更
3. 故障处理:
Master 失联 → 其他节点发起新选举
分区节点 → 无法达成多数票 → 只读
生产配置:
# elasticsearch.yml
cluster.name: production-logs
node.name: node-data-1
node.roles: [data]
# 种子节点配置(7.x+)
discovery.seed_hosts:
- master-1:9300
- master-2:9300
- master-3:9300
# 初始集群引导(首次启动)
cluster.initial_master_nodes:
- master-1
- master-2
- master-3
# 网络配置
network.host: 0.0.0.0
http.port: 9200
transport.port: 9300
常见问题:
"master_not_discovered_exception"
→ 种子节点配置错误 / 网络不通
无法形成集群
→ discovery.seed_hosts 缺失或域名无法解析
脑裂(拆分集群)
→ 老版本 Zen Discovery 未配 minimum_master_nodes
→ 7.x+ Raft 协议内置防脑裂
12 Elasticsearch 集群的故障恢复流程(Primary 重分配、Replica 同步)是怎样的?
答案:
当节点故障时,Elasticsearch 自动触发数据恢复流程,涉及 Primary Relocation、Replica 分配和 Sync Flush。
恢复流程:
graph TD
A["节点故障"] --> B["Master 检测到节点离线<br/>(30s 无心跳)"]
B --> C["重新分配该节点上的 Primary Shard"]
C --> D{"检查同分片的 Replica 是否可用"}
D -->|可用| E["提升为 Primary"]
D -->|不可用| F["从其他节点复制数据"]
E --> G["创建新的 Replica 副本"]
F --> G
G --> H["触发 Recovery 过程"]
Recovery 过程:
1. Phase 1: 同步 Translog(增量数据)
2. Phase 2: 索引 Segment 文件
3. Phase 3: 启用分片(允许搜索)
恢复参数调优:
PUT /_cluster/settings
{
"persistent": {
"cluster.routing.allocation.node_concurrent_recoveries": 4,
"cluster.routing.allocation.node_initial_primaries_recoveries": 5,
"indices.recovery.max_bytes_per_sec": "200mb",
"indices.recovery.max_concurrent_file_chunks": 5
}
}
慢恢复排查:
| 现象 | 原因 | 解决方案 |
|---|---|---|
| 恢复速度慢 | max_bytes_per_sec 过小 | 增加到 200mb+ |
| 恢复卡住 | 磁盘空间不足 | 清理 ILM 或扩展存储 |
| 恢复失败 | 分片损坏 | POST /index/_shrink 或重新索引 |
| 快照恢复慢 | 快照仓库 I/O 瓶颈 | 使用 S3/GCS 并行批量 |
13 Logstash 的 Pipeline 架构由哪些部分组成?各阶段的功能是什么?
答案:
Logstash 采用基于事件的数据处理管道模型,由 Input、Filter、Output 三阶段顺序执行。
Pipeline 架构:
Input Plugin → Filter Pipeline → Output Plugin
│ │ │
数据输入 处理/转换 数据输出
(stdin/file (grok/date (elasticsearch
/kafka/ /mutate/ /kafka
/beats) /kv/ruby) /s3)
默认工作线程配置:
# pipelines.yml 或 config/logstash.yml
pipeline.workers: 4 # = CPU Cores
pipeline.batch.size: 125 # 每批事件数
pipeline.batch.delay: 50 # 批处理等待(ms)
完整配置示例:
input {
beats {
port => 5044
ssl => true
ssl_certificate_authorities => ["/etc/logstash/ca.crt"]
ssl_certificate => "/etc/logstash/server.crt"
ssl_key => "/etc/logstash/server.key"
}
}
filter {
# 解析时间戳
date {
match => ["timestamp", "ISO8601", "yyyy-MM-dd HH:mm:ss"]
target => "@timestamp"
}
# Grok 解析 Nginx 日志
grok {
match => {
"message" => "%{COMBINEDAPACHELOG}"
}
}
# GeoIP 解析
geoip {
source => "clientip"
target => "geo"
database => "/etc/logstash/GeoLite2-City.mmdb"
}
# 类型转换
mutate {
convert => { "response" => "integer" }
convert => { "bytes" => "integer" }
rename => { "response" => "status" }
}
}
output {
elasticsearch {
hosts => ["https://es-node:9200"]
index => "nginx-logs-%{+YYYY-MM-dd}"
user => "logstash_writer"
password => "${ES_PASSWORD}"
ssl => true
}
# 失败事件写入死信队列
if "_grokparsefailure" in [tags] {
file {
path => "/var/log/logstash/failed/%{+YYYY-MM-dd}-parse-failure.log"
}
}
}
多 Pipeline 配置:
# pipelines.yml
- pipeline.id: nginx
path.config: "/etc/logstash/conf.d/nginx.conf"
pipeline.workers: 4
- pipeline.id: syslog
path.config: "/etc/logstash/conf.d/syslog.conf"
pipeline.workers: 2
- pipeline.id: docker
path.config: "/etc/logstash/conf.d/docker.conf"
pipeline.workers: 4
14 Logstash 的 Grok 模式匹配的工作原理是什么?如何编写自定义 Grok 模式?
答案:
Grok 是 Logstash 用于将非结构化文本解析为结构化数据的过滤器插件,本质上是基于命名正则表达式的模式匹配系统。
Grok 语法:
%{SYNTAX:SEMANTIC:TYPE}
%{IP:clientip} → 匹配 IP 地址,字段名 clientip
%{NUMBER:response:int} → 匹配数字,字段名 response,类型 int
%{TIMESTAMP_ISO8601:timestamp} → 匹配 ISO 时间戳
Grok 内置模式分类:
| 类别 | 示例模式 | 用途 |
|---|---|---|
| 网络 | IP、HOSTNAME、MAC、PORT | IP/域名匹配 |
| 系统 | SYSLOGBASE、UNIXPATH | 系统日志 |
| Web | HTTPD_COMMONLOG、URIPATHPARAM | Web 日志 |
| 时间 | TIMESTAMP_ISO8601、DATESTAMP | 时间提取 |
| 数值 | NUMBER、INTEGER、FLOAT、BASE16NUM | 数值提取 |
Nginx 访问日志解析:
filter {
grok {
match => { "message" => "%{IPORHOST:clientip} - %{USERNAME:auth} \[%{HTTPDATE:timestamp}\] \"%{WORD:method} %{URIPATHPARAM:request} HTTP/%{NUMBER:httpversion}\" %{NUMBER:response:int} %{NUMBER:bytes:int} \"%{DATA:referrer}\" \"%{DATA:agent}\"" }
remove_field => ["message", "auth"]
add_field => { "received_at" => "%{@timestamp}" }
}
}
自定义模式:
# 方式1:patterns_dir 目录
# /etc/logstash/patterns/custom_patterns
MYSQL_SLOW_QUERY \A# User@Host: %{USER:user}\[%{DATA:db}\]
QUERY_TIME %{NUMBER:query_time:float}
LOCK_TIME %{NUMBER:lock_time:float}
ROWS_SENT %{NUMBER:rows_sent:int}
ROWS_EXAMINED %{NUMBER:rows_examined:int}
# 方式2:patterns_dir 配置
filter {
grok {
patterns_dir => ["/etc/logstash/patterns"]
match => { "message" => "%{MYSQL_SLOW_QUERY} %{QUERY_TIME} %{LOCK_TIME} %{ROWS_SENT} %{ROWS_EXAMINED}" }
}
}
# 方式3:内联定义
filter {
grok {
match => { "message" => "(?<custom_field>\\d{3}-\\d{2}-\\d{4})" }
}
}
调试方法:
# 命令行验证
bin/logstash -e 'input { stdin { } } filter { grok { match => { "message" => "%{COMBINEDAPACHELOG}" } } } output { stdout { codec => rubydebug } }'
# 输入测试日志
192.168.1.1 - - [26/May/2026:10:30:00 +0800] "GET /api/v1/users HTTP/1.1" 200 1234 "-" "curl/7.68.0"
15 Logstash 的多行日志(Multiline)处理如何配置?
答案:
Logstash 的 Multiline Codec/Filter 用于合并跨多行的日志事件(如 Java 异常堆栈、SQL 慢查询)。
Multiline Codec(输入侧):
input {
file {
path => "/var/log/app/error.log"
codec => multiline {
pattern => "^\["
negate => true
what => "previous"
max_lines => 500
max_bytes => "10MB"
auto_flush_interval => 5
}
}
}
Multiline Filter(处理侧):
filter {
# Java 异常堆栈合并
multiline {
pattern => "^\s*(at|Caused by|\.{3}\d+ more)"
negate => false
what => "previous"
}
# MySQL 慢查询合并
multiline {
pattern => "^# (Time|User|Query_time|Thread_id|Schema)"
negate => true
what => "previous"
}
}
| 参数 | 说明 | 默认值 |
|---|---|---|
pattern | 行匹配正则 | 必填 |
negate | 模式匹配取反 | false |
what | 合并方向(previous/next) | previous |
max_lines | 最大合并行数 | 500 |
max_bytes | 最大合并字节数 | 10MB |
auto_flush_interval | 自动刷新间隔(秒) | 无 |
Java 异常堆栈合并示例:
# 原始多行
2026-05-26 10:30:00 ERROR - NullPointerException
at com.example.service.UserService.getUser(UserService.java:25)
at com.example.controller.UserController.handle(UserController.java:10)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:900)
Caused by: java.lang.RuntimeException: Database connection failed
at com.example.dao.UserDao.findById(UserDao.java:45)
... 10 more
# 合并后(单条 Logstash 事件)
message: "2026-05-26 10:30:00 ERROR - NullPointerException\n at com.example.service.UserService.getUser(UserService.java:25)\n ..."
16 Logstash 的 Queue 类型(Memory vs Persistent)的选择依据是什么?
答案:
Logstash 提供内存队列和持久化队列两种事件缓冲机制,用于应对突发流量和下游故障。
队列类型对比:
| 维度 | Memory Queue | Persistent Queue |
|---|---|---|
| 存储 | 内存(堆内) | 磁盘(MMAP) |
| 延迟 | 极低 | 较低 |
| 吞吐量 | 高 | 中 |
| 容错 | 进程崩溃丢失 | 进程重启可恢复 |
| 磁盘占用 | 无 | 需规划 |
| 背压 | 有限 | 强 |
配置方式:
# config/logstash.yml
# 内存队列(默认)
queue.type: memory
queue.max_bytes: 1gb
# 持久化队列
queue.type: persisted
queue.max_bytes: 8gb
queue.drain: true # 关闭时排空队列
queue.max_events: 0 # 0=不限,按字节限制
queue.checkpoint.writes: 1024 # 每 N 条写入 checkpoint
事件生命周期:
Input → Queue → Filter Worker → Output Worker
│
Memory In-Process
│ 或
Persistent Queue (Disk)
选型建议:
| 场景 | 推荐队列 | 说明 |
|---|---|---|
| 流水丢失可接受 | Memory | 最低延迟最高吞吐 |
| 关键日志不可丢失 | Persistent | 至少一次投递保证 |
| 下游(ES/Kafka)不稳定 | Persistent | 缓冲积压能力更强 |
| 高吞吐场景 | Memory + 快速下游 | 避免磁盘 I/O 瓶颈 |
| 内存受限 | Persistent | 堆内存压力转移到磁盘 |
17 Kibana 的 Discover、Dashboard 和 Lens 三种数据探索方式的区别是什么?
答案:
Kibana 提供了三种互补的数据探索与可视化方式,满足不同角色的分析需求。
功能对比:
| 维度 | Discover | Dashboard | Lens |
|---|---|---|---|
| 定位 | 原始日志浏览 | 组合仪表盘 | 拖拽式可视化 |
| 交互方式 | 搜索栏 + 过滤 | 面板编排 | 可视化向导 |
| 适合用户 | 运维/开发 | 管理层/全员 | 数据分析师 |
| 灵活性 | 低(固定表格) | 中(面板组合) | 高(拖拽) |
| 保存方式 | 搜索条件 | 仪表盘 | 可视化图表 |
| 过滤能力 | KQL 查询 | 全局+面板过滤 | 维度筛选 |
| 临时分析 | 支持 | 不支持 | 支持 |
Discover 场景:
Kibana → Discover
1. 选择数据视图 (logs-nginx-*)
2. 查询: response: 500
3. 过滤 @timestamp > now-1h
4. 查看原始日志字段
5. 保存搜索条件为 "5XX错误"
Dashboard 场景:
Kibana → Dashboard
面板类型:
├── 时序图:请求量、延迟 P50/P95/P99
├── 饼图:HTTP 状态码分布
├── 数据表格:Top N 客户端 IP
├── 地图:GeoIP 请求来源
└── 数字:错误率、总请求量
Lens 场景:
Kibana → Lens
1. 拖拽 @timestamp 到 X 轴
2. 拖拽 response 到 Y 轴(Count)
3. 拖拽 status_code.keyword 到分组(Break down)
4. 自动选择合适的图表类型(折线/柱状/面积)
KQL(Kibana Query Language)示例:
# 精确匹配
response: 500
# 范围查询
latency_ms > 1000
# 逻辑组合
response: 500 AND agent: "Mozilla/*"
# 嵌套字段
request.path: /api/*
# 存在性检查
exists: error_trace
# 否定查询
NOT level: DEBUG
18 Elasticsearch 的索引生命周期管理(ILM)如何配置?冷热架构如何实现?
答案:
ILM(Index Lifecycle Management)是 Elasticsearch 内置的索引自动管理机制,支持基于索引年龄、大小或文档数的自动化阶段流转。
ILM 阶段:
Hot (热) → Warm (温) → Cold (冷) → Frozen (冻结) → Delete (删除)
│ │ │ │ │
写入 降低副本 只读+压缩 极低成本 永久删除
ILM Policy 定义:
PUT /_ilm/policy/logs_retention
{
"policy": {
"phases": {
"hot": {
"min_age": "0ms",
"actions": {
"rollover": {
"max_age": "1d",
"max_size": "50gb",
"max_docs": 10000000
},
"set_priority": { "priority": 100 }
}
},
"warm": {
"min_age": "3d",
"actions": {
"allocate": {
"include": { "data_type": "warm" }
},
"shrink": { "number_of_shards": 1 },
"forcemerge": { "max_num_segments": 1 },
"set_priority": { "priority": 50 }
}
},
"cold": {
"min_age": "15d",
"actions": {
"allocate": {
"include": { "data_type": "cold" }
},
"freeze": {},
"set_priority": { "priority": 0 }
}
},
"delete": {
"min_age": "30d",
"actions": {
"delete": {}
}
}
}
}
}
索引模板关联 ILM:
PUT /_index_template/logs-nginx
{
"index_patterns": ["logs-nginx-*"],
"template": {
"settings": {
"index.lifecycle.name": "logs_retention",
"index.lifecycle.rollover_alias": "logs-nginx",
"number_of_shards": 3,
"number_of_replicas": 1,
"routing.allocation.require.data_type": "hot"
}
}
}
冷热节点配置:
# 热节点 elasticsearch.yml
node.roles: [data_hot, data_content]
node.attr.data_type: hot
# 温节点 elasticsearch.yml
node.roles: [data_warm, data_content]
node.attr.data_type: warm
# 冷节点 elasticsearch.yml
node.roles: [data_cold, data_content]
node.attr.data_type: cold
ILM 指标监控:
# 查看 ILM 执行状态
GET /_ilm/status
# 查看索引当前阶段
GET /logs-nginx-*/_ilm/explain
# 手动触发重试
POST /logs-nginx-000001/_ilm/retry
# 移除 ILM 策略
PUT /logs-nginx-000001/_settings
{
"index.lifecycle.name": null
}
19 Elasticsearch 的索引模板(Index Template)和组件模板(Component Template)的区别和使用场景是什么?
答案:
索引模板定义新索引的 settings、mappings 和 aliases 的自动化配置。7.8+ 引入组件模板实现模板组合复用。
模板类型对比:
| 维度 | Legacy Index Template | Index Template (v2) | Component Template |
|---|---|---|---|
| 定义位置 | _template | _index_template | _component_template |
| 优先级 | 低(先匹配) | 高(后覆盖) | 中 |
| 组合能力 | 无 | 引用多个 Component | 可被多个模板复用 |
| 推荐 | 废弃 | 当前标准 | 当前标准 |
Index Template (v2) 示例:
PUT /_index_template/logs-template
{
"index_patterns": ["logs-*", "metrics-*"],
"template": {
"settings": {
"number_of_shards": 3,
"number_of_replicas": 1,
"index.lifecycle.name": "logs_retention",
"index.codec": "best_compression"
},
"mappings": {
"dynamic": "strict",
"properties": {
"@timestamp": { "type": "date" },
"message": { "type": "text" },
"host": { "type": "keyword" },
"env": { "type": "keyword" }
}
}
},
"priority": 200
}
Component Template 组合:
// 基础设置模板
PUT /_component_template/logs-settings
{
"template": {
"settings": {
"number_of_shards": 3,
"number_of_replicas": 1,
"index.lifecycle.name": "logs_retention",
"index.codec": "best_compression"
}
}
}
// 基础映射模板
PUT /_component_template/logs-mappings
{
"template": {
"mappings": {
"properties": {
"@timestamp": { "type": "date" },
"message": { "type": "text" },
"host": { "type": "keyword" }
}
}
}
}
// 组合成索引模板
PUT /_index_template/nginx-logs-template
{
"index_patterns": ["nginx-logs-*"],
"composed_of": ["logs-settings", "logs-mappings"],
"priority": 300,
"template": {
"settings": {
"index.number_of_shards": 2
}
}
}
优先级匹配规则:
多个模板匹配同一索引 → priority 最高的生效
Index Template v2 > Component Template > Legacy Template
通配符范围越精确,priority 越高
20 Elasticsearch 的写入性能优化参数有哪些?如何调整?
答案:
ES 写入性能优化涉及 Refresh Interval、Translog、Bulk API、线程池配置及硬件层面优化。
核心优化参数:
PUT /_template/optimized-write
{
"template": {
"settings": {
"index.refresh_interval": "30s",
"index.translog.durability": "async",
"index.translog.sync_interval": "5s",
"index.number_of_replicas": 0,
"index.number_of_shards": 5,
"index.sort.field": "@timestamp",
"index.sort.order": "desc",
"index.merge.scheduler.max_thread_count": 2
}
}
}
各参数效果:
| 参数 | 默认值 | 优化值 | 效果 |
|---|---|---|---|
refresh_interval | 1s | 30s-60s | 减少 refresh 开销 |
translog.durability | request | async | 降低每次写入 fsync 开销 |
number_of_replicas | 1 | 0(写入时) | 避免复制开销 |
index.sort | 无 | @timestamp desc | 提升范围查询性能 |
merge.scheduler.max_thread_count | max(1, min(4, CPUs)) | 1-2 | 降低合并 I/O 竞争 |
Bulk API 优化:
POST /_bulk
{ "index": { "_index": "logs-nginx-000001", "_id": null } }
{ "message": "GET /api 200 100ms", "@timestamp": "2026-05-26T10:00:00Z", ... }
{ "index": { "_index": "logs-nginx-000001", "_id": null } }
{ "message": "POST /api 500 2000ms", "@timestamp": "2026-05-26T10:00:01Z", ... }
| 参数 | 推荐值 | 说明 |
|---|---|---|
| batch size | 5-15 MB / 1000-5000 条 | 过大增加 GC 压力 |
| concurrency | CPU cores × 2 | Go/Java 客户端参数 |
| compression | gzip | 减少网络带宽 |
| id | null(自动生成) | 避免 Get Before Index 开销 |
硬件与系统层面:
| 优化项 | 推荐 | 说明 |
|---|---|---|
| 存储 | SSD / NVMe | 随机 I/O 性能关键 |
| 内存 | 50% 分配给 ES Heap | 剩余留给 OS Page Cache |
| Swap | swapiness=1 | 避免交换 |
| 磁盘挂载 | noatime + nobarrier | 减少写入开销 |
| 网络 | 10GbE | 节点间复制/恢复带宽 |
线程池配置(仅 7.x 手动配置适用):
# elasticsearch.yml
thread_pool:
write:
fixed:
size: 16 # CPU cores × 2
queue_size: 10000 # 最大待处理请求
search:
thread_pool_type: fixed
size: 24
queue_size: 1000
21 Elasticsearch 查询性能优化策略有哪些?
答案:
ES 查询性能优化涵盖查询设计、索引优化、节点配置和分片策略四个维度。
查询层面优化:
// 使用过滤器上下文(不评分,缓存)
GET /logs/_search
{
"query": {
"bool": {
"filter": [
{ "term": { "status": "500" } },
{ "range": { "@timestamp": { "gte": "now-1h" } } }
]
}
}
}
// 避免通配符前缀查询
// ❌ 慢
{ "wildcard": { "path": "/api/*" } }
// ✅ 快
{ "prefix": { "path": "/api/" } }
// 使用 keyword 字段做聚合排序
GET /logs/_search
{
"aggs": {
"top_hosts": {
"terms": {
"field": "host.keyword", // 确保是 keyword
"size": 10,
"shard_size": 100
}
}
}
}
索引层面优化:
| 策略 | 做法 | 效果 |
|---|---|---|
| Force Merge | 只读索引合并为 1 个 segment | 减少 _search 开销 |
| Shrink | 减少分片数 | 提高单分片效率 |
| Sort | 按查询模式排序 | 加速范围查询 |
| Mapping | index: false 非搜索字段 | 减少索引大小 |
| Source | _source: false 或 excludes | 减少存储(日志场景) |
查询缓存:
// 节点查询缓存(LRU)
PUT /_cluster/settings
{
"persistent": {
"indices.queries.cache.size": "10%" // 堆内存 10%
}
}
// Shard 请求缓存(仅 filter 上下文)
PUT /_cluster/settings
{
"persistent": {
"indices.requests.cache.size": "1%" // 堆内存 1%
}
}
分片与节点:
| 维度 | 推荐 |
|---|---|
| 单分片大小 | 20-50GB |
| 总分片数 | < 10,000 / 集群 |
| 单节点分片数 | < 1,000 |
| Coordinating 节点 | 2-4 台 |
慢查询排查:
PUT /_cluster/settings
{
"persistent": {
"index.search.slowlog.threshold.query.warn": "10s",
"index.search.slowlog.threshold.query.info": "5s",
"index.search.slowlog.threshold.query.debug": "2s",
"index.search.slowlog.threshold.fetch.debug": "1s",
"index.search.slowlog.level": "info"
}
}
// 查看慢日志
GET /logs-nginx-*/_search?q=message:slowlog
22 Elasticsearch 集群的监控指标有哪些?关键性能指标如何解读?
答案:
ES 集群监控涵盖集群健康、节点资源、分片分布、搜索/写入性能、GC 和磁盘六个维度。
集群健康:
GET /_cluster/health
{
"status": "yellow",
"timed_out": false,
"number_of_nodes": 5,
"number_of_data_nodes": 3,
"active_primary_shards": 120,
"active_shards": 220,
"unassigned_shards": 10, // ❌ 存在未分配分片
"delayed_unassigned_shards": 0,
"number_of_pending_tasks": 0
}
关键指标速查表:
| 指标 | API | 正常范围 | 告警阈值 |
|---|---|---|---|
| Cluster Status | _cluster/health | green | yellow/red |
| CPU | _nodes/stats | < 70% | > 85% |
| Heap Usage | _nodes/stats/jvm | < 75% | > 85% |
| GC Rate | _nodes/stats/jvm/gc | < 1次/分钟 | > 5次/分钟 |
| GC Duration | _nodes/stats/jvm/gc | < 200ms | > 1s |
| Search QPS | _nodes/stats/indices/search | 基准基线 | > 2× 基线 |
| Search Latency | _nodes/stats/indices/search | < 100ms | > 1s |
| Indexing QPS | _nodes/stats/indices/indexing | 基准基线 | 下降 50% |
| Bulk Rejection | _nodes/stats/thread_pool/bulk | 0 | > 0 |
| Disk Usage | _cat/allocation | < 75% | > 85% |
| Open File Descriptors | _nodes/stats/process | < 80% of max | > 90% |
分片分布检查:
# 查看各节点分片数量是否均衡
GET _cat/shards?v
# 查看未分配分片原因
GET _cluster/allocation/explain
# 磁盘使用分布
GET _cat/allocation?v&h=node,shards,disk.percent,disk.used,disk.avail
Prometheus 告警规则(结合 elasticsearch_exporter):
groups:
- name: elasticsearch
rules:
- alert: ESClusterStatusRed
expr: elasticsearch_cluster_health_status{color="red"} == 1
for: 2m
- alert: ESNodeHeapHigh
expr: elasticsearch_jvm_memory_heap_pool_used_bytes / elasticsearch_jvm_memory_heap_pool_max_bytes > 0.85
for: 5m
- alert: ESBulkRejection
expr: rate(elasticsearch_thread_pool_rejected_count{type="bulk"}[1m]) > 0
for: 1m
- alert: ESDiskLowSpace
expr: elasticsearch_filesystem_data_available_bytes / elasticsearch_filesystem_data_size_bytes < 0.15
for: 5m
23 Elasticsearch 的快照(Snapshot)与恢复(Restore)机制如何工作?仓库和策略如何配置?
答案:
ES 的 Snapshot API 实现索引数据的增量备份和恢复,支持 S3/GCS/Azure/NFS/HDFS 等多种仓库后端。
Snapshot 架构:
ES 节点 → Snapshot API → Repository → Storage Backend
│
├── S3/GCS
├── NFS 共享存储
└── HDFS
仓库注册:
// S3 仓库
PUT /_snapshot/logs_backup
{
"type": "s3",
"settings": {
"bucket": "elasticsearch-snapshots",
"region": "ap-southeast-1",
"base_path": "production/logs",
"compress": true,
"chunk_size": "256mb",
"max_snapshot_bytes_per_sec": "200mb",
"max_restore_bytes_per_sec": "200mb"
}
}
快照策略(SLM):
PUT /_slm/policy/daily-snapshot
{
"name": "<logs-snapshot-{now/d}>",
"schedule": "0 0 2 * * ?",
"repository": "logs_backup",
"config": {
"indices": ["logs-*", "metrics-*"],
"ignore_unavailable": true,
"include_global_state": false
},
"retention": {
"expire_after": "30d",
"min_count": 7,
"max_count": 90
}
}
增量快照原理:
首次快照:完整拷贝
Snapshot 1 → segments_ref + .blob files(全量)
后续快照:仅变更的分片
Snapshot 2 → 仅记录变更 segment(增量快照)
Snapshot 3 → 仅记录变更 segment
删除快照:引用计数 decrement
仅在无引用时物理删除数据
恢复操作:
// 查看可用快照
GET /_snapshot/logs_backup/_all
// 恢复单索引
POST /_snapshot/logs_backup/logs-snapshot-2026.05.26/_restore
{
"indices": "logs-nginx-2026.05.26",
"rename_pattern": "logs-(.+)",
"rename_replacement": "restored-logs-$1",
"ignore_index_settings": [
"index.lifecycle.name",
"index.routing.allocation.require.data_type"
]
}
// 监控恢复进度
GET /_recovery/restored-logs-nginx-2026.05.26
24 Elasticsearch 的安全功能(Security)包括哪些方面?如何配置基于角色的访问控制?
答案:
Elastic Stack Security(原 X-Pack Security)提供认证、授权、审计、加密和字段级安全功能。
安全功能矩阵:
| 功能 | 说明 | 配置项 |
|---|---|---|
| Authentication | 身份认证 | Native/LDAP/AD/SAML/OIDC/PKI |
| Authorization | 基于角色的权限控制 | Role + User + Privilege |
| Audit | 审计日志 | xpack.security.audit.enabled |
| TLS/SSL | 节点间/HTTP 加密 | xpack.security.transport.ssl |
| Field/Document Level Security | 字段/文档级安全 | query + fields 权限 |
| IP Filtering | IP 白名单 | xpack.security.http.filter |
角色定义:
POST /_security/role/logs_admin
{
"cluster": ["monitor", "manage_ilm", "manage_index_templates"],
"indices": [
{
"names": ["logs-*"],
"privileges": ["read", "write", "maintenance"],
"field_security": {
"grant": ["@timestamp", "message", "level", "request.*"],
"except": ["password", "token", "credit_card"]
}
}
],
"applications": [
{
"application": "kibana-.kibana",
"privileges": ["feature_dashboard.read", "feature_discover.read"],
"resources": ["space:default"]
}
]
}
用户创建:
POST /_security/user/logstash_writer
{
"password": "super-secret-password",
"roles": ["logstash_writer"],
"full_name": "Logstash Service Account",
"metadata": { "service": "logstash" }
}
TLS 配置:
# elasticsearch.yml
xpack.security.enabled: true
xpack.security.transport.ssl.enabled: true
xpack.security.transport.ssl.verification_mode: certificate
xpack.security.transport.ssl.keystore.path: /etc/elasticsearch/certs/elastic-certificates.p12
xpack.security.transport.ssl.truststore.path: /etc/elasticsearch/certs/elastic-certificates.p12
xpack.security.http.ssl.enabled: true
xpack.security.http.ssl.keystore.path: /etc/elasticsearch/certs/http.p12
常见权限场景:
| 场景 | 所需角色 | privileges |
|---|---|---|
| 只读用户(Discover) | logs_reader | read + kibana_dashboard_read |
| 写入用户(Logstash) | logstash_writer | create_index + write + manage |
| 运维管理员 | ops_admin | monitor + manage_slm + manage_ilm |
| 超级管理员 | superuser | all(内置) |
| 跨集群复制 | ccr_user | manage_ccr + read_ccr |
25 Elasticsearch 的 Circuit Breaker 机制有哪些类型?如何防止 OOM?
答案:
Circuit Breaker 是 ES 防止内存溢出(OOM)的关键保护机制,在内存使用超过阈值时拒绝请求。
Circuit Breaker 类型:
| 名称 | 监控范围 | 默认阈值 | 触发的异常 |
|---|---|---|---|
| Parent | 所有 Circuit Breaker 总和 | 70% JVM Heap | CircuitBreakingException |
| Fielddata | 字段数据缓存 | 40% JVM Heap | - |
| Request | 请求数据结构 | 60% JVM Heap | - |
| In Flight | 传输层请求 | 100%(仅计数) | - |
| Accounting | 可释放内存 | 100% | - |
触发场景与表现:
# 内存断路器触发
{
"type": "circuit_breaking_exception",
"reason": "[parent] Data too large, data for [<http_request>]
would be [2.5gb/2.7gb], which is larger than the
limit of [2.4gb/2.5gb]",
"bytes_wanted": 2684354560,
"bytes_limit": 2576980377
}
配置调优:
# elasticsearch.yml
# 总断路器阈值(默认 70%,不建议超过 85%)
indices.breaker.total.limit: 75%
# Fielddata 断路器(默认 40%,高聚合建议降低)
indices.breaker.fielddata.limit: 30%
# Request 断路器(默认 60%)
indices.breaker.request.limit: 50%
OOM 防护体系:
内存保护三层架构:
1. Circuit Breaker(主动拒绝)
请求前估算内存 → 超过阈值 → 拒绝异常
2. GC(被动回收)
堆内存持续上升 → GC 回收 → 回收不足触发断路器
3. JVM 参数(系统级)
-Xms/-Xmx(堆大小)
-XX:MaxDirectMemorySize(直接内存)
-XX:+ExitOnOutOfMemoryError(OOM 退出)
最佳实践:
| 措施 | 说明 |
|---|---|
| 堆内存 ≤ 50% 物理内存 | 剩余留给 OS Page Cache |
| 堆大小 ≤ 32GB | 超过 32GB JVM 禁用压缩指针 |
| 避免高基数 terms 聚合 | 100M+ 唯一值聚合触发断路器 |
| 控制分页深度 | search.max_buckets 默认 65535 |
| 监控 Fielddata 使用 | 高 Fielddata → 降低阈值或使用 doc_values |
| 启用 ExitOnOOM | OOM 时主动退出,避免服务降级 |
26 Elasticsearch 集群升级策略有哪些?滚动升级和全集群升级的区别是什么?
答案:
ES 集群升级主要分滚动升级和全集群升级,6.x → 7.x → 8.x 跨大版本升级需遵循特定路径。
升级方式对比:
| 维度 | 滚动升级 | 全集群升级 |
|---|---|---|
| 停机时间 | 无(逐一重启) | 需完全停机 |
| 兼容性 | N-1 版本兼容 | 任意版本跳转 |
| 耗时 | 较长 | 短 |
| 风险 | 低 | 高 |
| 适用场景 | 小版本升级 | 大版本跨级升级 |
滚动升级流程(7.x → 8.x):
1. 停止 Reindex、Shard 分配
PUT _cluster/settings
{ "transient": { "cluster.routing.allocation.enable": "none" } }
2. POST _flush/synced(确保日志同步)
3. 逐节点操作:
a. 停止 ES 服务
b. 升级安装包/容器镜像
c. 启动 ES 验证加入集群
d. 等待分片恢复正常
4. 恢复分片分配
PUT _cluster/settings
{ "transient": { "cluster.routing.allocation.enable": "all" } }
5. 验证集群健康
GET _cluster/health?wait_for_status=green&timeout=50s
版本兼容性矩阵:
6.8 → 7.0 需跨版本升级(6.8→7.0→7.17→8.x)
6.8 ← 7.0 不可回滚
7.17 → 8.x 支持 N-1 兼容(最后一个 7.x 版本)
7.0 → 7.17 ☑ 滚动升级
8.0 → 8.5+ ☑ 滚动升级
升级注意事项(8.x 重大变更):
| 变更 | 影响 | 解决方案 |
|---|---|---|
| Mapping types 移除 | 多 type 索引需 reindex | reindex API |
| _doc 作为固定 type | 客户端兼容性 | 升级客户端 SDK |
| Security 默认启用 | 需要 TLS 配置 | 配置证书或关闭 |
| Minimum Master Nodes 废弃 | 替换为 Raft | 升级配置移除 |
删除 yaml 内 path.data | 需要单独指定 | 保留配置 |
27 Elasticsearch 的跨集群搜索(Cross Cluster Search, CCS)和跨集群复制(Cross Cluster Replication, CCR)的区别是什么?
答案:
CCS 实现跨集群的实时查询能力,CCR 实现跨集群的数据同步复制,两者解决不同的分布式需求。
功能对比:
| 维度 | CCS | CCR |
|---|---|---|
| 定位 | 搜索层联邦 | 数据层复制 |
| 数据流向 | 查询发起→远程集群 | 主动→被动集群 |
| 实时性 | 实时查询远程数据 | 近实时(~1s 延迟) |
| 存储 | 不存储数据 | 远程存储完整副本 |
| 网络依赖 | 查询时 | 持续连接 |
| 带宽消耗 | 低(仅查询结果) | 高(全量复制) |
CCS 配置:
// 远程集群注册
PUT /_cluster/settings
{
"persistent": {
"cluster.remote": {
"dc2-cluster": {
"seeds": ["es-dc2-node1:9300", "es-dc2-node2:9300"],
"mode": "sniff",
"transport.ping_schedule": "30s"
}
}
}
}
// 跨集群查询(dc2-cluster 前缀)
GET /dc2-cluster:logs-*/_search
{
"query": { "match": { "status": "500" } }
}
// 跨集群聚合
GET /dc2-cluster:metrics-*/_search
{
"aggs": {
"avg_latency": { "avg": { "field": "latency_ms" } }
}
}
CCR 配置:
// 被动集群注册远程主动集群
PUT /_cluster/settings
{
"persistent": {
"cluster.remote": {
"dc1-cluster": {
"seeds": ["es-dc1-node1:9300"],
"mode": "sniff"
}
}
}
}
// 创建 follower 索引
PUT /dc2-logs-nginx/_ccr/follow?wait_for_active_shards=1
{
"remote_cluster": "dc1-cluster",
"leader_index": "logs-nginx"
}
// 查看复制状态
GET /dc2-logs-nginx/_ccr/info
选型场景:
| 需求 | 建议方案 |
|---|---|
| 多数据中心查询聚合 | CCS |
| 灾备(主动→被动复制) | CCR |
| 数据本地化(合规要求) | CCR |
| 跨集群迁移 | CCR + CCS |
| 实时全局搜索 | CCS |
| 读写分离 | CCR(只读副本) |
28 Elasticsearch 的索引排序(Index Sorting)对查询性能有什么影响?
答案:
Index Sorting 在索引创建时定义文档的物理排序顺序,影响 Segment 合并效率和范围查询性能。
工作原理:
无排序:
Segment 内文档无序存储
有排序(@timestamp desc):
Segment 内文档按时间降序排列
↓
优点:
- 时间范围查询可提前终止
- Segment 合并时可高效增量合并
- 提升存储压缩率(相邻文档相似度高)
配置方法:
PUT /logs-index-sorted
{
"settings": {
"index": {
"sort.field": ["@timestamp", "host"],
"sort.order": ["desc", "asc"]
}
},
"mappings": {
"properties": {
"@timestamp": { "type": "date" },
"host": { "type": "keyword" },
"message": { "type": "text" }
}
}
}
性能影响:
| 场景 | 无排序 | 有排序 | 提升 |
|---|---|---|---|
| 最近 N 条查询 | 全表扫描 | 取前 N 条 | 10-100× |
| 按时间范围查询 | 扫描全部 | 二分查找定位 | 5-10× |
| 聚合排序 | 额外排序 | 数据有序 | 2-5× |
| Segment 合并 | 增量较小 | 增量更大 | 合并加速 |
限制条件:
- 必须在索引创建时设置,创建后不可修改
- 最多支持 4 个排序列
- 写入性能略有下降(写入时需排序)
- 自定义排序优先级高于 Lucene 内部排序
最佳实践:
日志场景:sort.field = ["@timestamp"], sort.order = ["desc"]
指标场景:sort.field = ["timestamp", "host"], sort.order = ["desc", "asc"]
应用事件:sort.field = ["event_time"], sort.order = ["desc"]
29 Kibana 的 Alerting 和 Watcher(Elasticsearch Alerting)的区别是什么?如何配置告警规则?
答案:
Watcher 是 Elasticsearch 层面的告警引擎(仅白金版),Kibana Alerting 是 7.x+ 引入的轻量级内置告警框架。
功能对比:
| 维度 | ES Watcher | Kibana Alerting |
|---|---|---|
| 层级 | ES 集群层 | Kibana 应用层 |
| 许可证 | 白金版 | 免费版(部分) |
| 规则编排 | JSON 定义 | UI 向导 + API |
| 规则类型 | 自定义脚本 | 预定义 + 自定义 |
| 数据源 | ES 查询 | ES 查询 |
| 行动 | Email/Slack/PagerDuty/Webhook | Email/Slack/Webhook/Index |
| 创建时间 | 2.x | 7.8+ |
| 推荐 | 旧版保留兼容 | 当前标准 |
Kibana Alerting 规则配置:
POST /api/alerting/rule
{
"name": "High 5XX Error Rate",
"rule_type_id": "observability.rules.custom_threshold",
"consumer": "alerts",
"schedule": { "interval": "1m" },
"params": {
"criteria": [
{
"comparator": ">",
"threshold": [5],
"timeSize": 5,
"timeUnit": "m",
"metrics": [
{ "name": "A", "aggregation": "count", "field": "status.keyword" }
]
}
],
"groupBy": ["host.keyword"],
"searchType": "query",
"excludeHitsFromPreviousTime": true,
"alertOnNoData": false
},
"actions": [
{
"group": "threshold met",
"id": "<connector-id>",
"params": {
"message": "Host XQOPENcontext.groupXQCLOSE 5XX errors > 5 in 5m"
}
}
]
}
Watcher 规则配置:
PUT /_watcher/watch/error_rate_alarm
{
"trigger": {
"schedule": { "interval": "5m" }
},
"input": {
"search": {
"request": {
"indices": ["logs-nginx-*"],
"body": {
"query": {
"bool": {
"filter": [
{ "range": { "@timestamp": { "gte": "now-5m" } } },
{ "prefix": { "status": "5" } }
]
}
},
"aggregations": {
"status_count": { "value_count": { "field": "status" } }
}
}
}
}
},
"condition": {
"compare": { "ctx.payload.aggregations.status_count.value": { "gt": 100 } }
},
"actions": {
"slack_alert": {
"slack": {
"message": "High error rate detected: XQOPENctx.payload.aggregations.status_count.valueXQCLOSE errors in 5m"
},
"webhook": {
"host": "hooks.example.com",
"port": 443,
"method": "POST",
"path": "/api/alert",
"body": "{\"text\":\"ES Alert: Error rate high\"}"
}
}
}
}
可用连接器类型:
| 连接器 | 触发方式 | 配置参数 |
|---|---|---|
| Slack | Webhook URL | webhookUrl |
| SMTP 服务 | host / port / user | |
| PagerDuty | Events API | routingKey |
| Webhook | 自定义 HTTP | url / method / headers |
| Index | ES 索引 | index / doc_id |
| ServerLog | Kibana 日志 | level |
30 如何排查 Elasticsearch 集群的常见故障(RED 状态、慢查询、OOM)?
答案:
ES 集群故障排查手册涵盖状态异常、性能瓶颈和稳定性问题三类场景。
场景一:Cluster Status RED(存在未分配主分片)
# 1. 定位未分配分片
GET _cluster/allocation/explain
# 2. 查看原因类型
# 常见原因:
# - 磁盘满 → INDEX_CREATED / NODE_LEFT
# - 配置限制 → REROUTE_NO_ATTEMPT
# - 分片损坏 → CORRUPTED_TRANSLOG / CORRUPTED_INDEX
# 3. 常见解决
# 磁盘满 → 清理或扩容
# 分片损坏 → reroute 或删除重建
POST /_cluster/reroute
{
"commands": [
{
"allocate_stale_primary": {
"index": "logs-nginx-2026.05.25",
"shard": 0,
"node": "node-data-1"
}
}
]
}
场景二:写入拒绝 / Bulk Rejection
# 1. 检查线程池状态
GET _cat/thread_pool?v&h=node_name,name,active,rejected,completed,queue,size
# 2. 检查队列积压
GET _nodes/stats/thread_pool
# 3. 常见原因与解决
# - 批量写入过大 → 减少 batch size(5-15 MB)
# - 分片数不足 → 增加分片数
# - GC 频繁 → 检查堆内存使用
# - 磁盘 I/O 饱和 → 检查 iowait 和磁盘利用率
# 4. 临时缓解(提高队列大小)
PUT /_cluster/settings
{
"persistent": {
"thread_pool.write.queue_size": 2000
}
}
场景三:查询慢 / 高延迟
# 1. 启用慢日志
PUT /logs-nginx-*/_settings
{
"index.search.slowlog.threshold.query.warn": "5s",
"index.search.slowlog.threshold.query.info": "2s"
}
# 2. Profile API 分析
GET /logs-nginx-*/_search
{
"profile": true,
"query": { "match": { "message": "error" } }
}
# 3. 热点线程(查看 CPU 消耗)
GET /_nodes/hot_threads
# 4. 常见原因
# - 未缓存 filter → 添加 filter 缓存
# - 分片过多 → 合并小索引
# - Wildcard / Regex 查询 → 改用 keyword + prefix
# - Deep pagination → 改用 search_after
场景四:OOM / Heap 波动
# 1. 检查 GC 情况
GET _nodes/stats/jvm/gc
# 重点指标:young_gc_count、young_gc_time、old_gc_count、old_gc_time
# 持续 Old GC > 1s → 接近 OOM
# 2. 检查 Fielddata 和 Circuit Breaker
GET _nodes/stats/breaker
# 3. 检查热点字段(高基数 aggregation)
# - terms 聚合字段的唯一值数量
# - 是否为 keyword 类型
# - 是否存在误用 text 类型做聚合
# 4. 缓解措施
# - 重启节点(临时)
# - 降低 breaker 阈值
# - 扩容节点或增加堆内存
故障排查速查表:
| 现象 | 排查命令 | 常见根因 |
|---|---|---|
| RED | _cluster/allocation/explain | 磁盘满、分片损坏 |
| YELLOW | _cat/shards | 副本未分配 |
| 拒绝请求 | _nodes/stats/thread_pool | 堆积、GC |
| 慢查询 | _search?profile=true | 非 filter 查询、全表扫描 |
| OOM | _nodes/stats/jvm/gc | Fielddata、大聚合、堆不足 |
| 高 CPU | _nodes/hot_threads | Merge 线程、搜索热点 |
| 连接超时 | _nodes/stats/http | 连接数耗尽 |
| 磁盘高 | _cat/allocation | ILM 未配置、缺乏轮转 |
31 Elasticsearch 的字段冻结(Freeze)和解冻(Unfreeze)机制是什么?何时使用?
答案:
Elasticsearch 7.x+ 的冻结索引(Frozen Index)是一种将索引置于低内存占用只读状态的能力。
冻结原理:
正常索引:所有数据和元数据在内存中可访问
冻结索引:仅保留最小元数据在内存(分段数、偏移量)
数据存储在磁盘,按需加载到内存
内存占用减少 90%+
操作命令:
// 冻结索引
POST /logs-nginx-2025.01/_freeze
// 解冻索引
POST /logs-nginx-2025.01/_unfreeze
// 通过 ILM 自动冻结
PUT /_ilm/policy/cold_storage
{
"policy": {
"phases": {
"cold": {
"min_age": "30d",
"actions": {
"freeze": true,
"allocate": { "include": { "data_type": "cold" } }
}
}
}
}
}
性能特征:
| 维度 | 正常索引 | 冻结索引 |
|---|---|---|
| 堆内存 | 高(全加载) | 极低(元数据) |
| 查询延迟 | ms 级 | s 级(首次查询需加载) |
| 写入 | 支持 | 不支持 |
| 存储 | 正常 | 正常 |
| 适用 | 近期活跃数据 | 历史归档查询 |
使用建议:
写入不超过 30 天的数据 → 活跃索引(Hot/Warm)
30-90 天数据 → 冻结索引(Cold)
90 天以上数据 → 快照 + 删除
32 Logstash 的多 Pipeline 编排(Multiple Pipelines)如何配置?Pipeline-to-Pipeline 通信机制是什么?
答案:
Logstash 支持多 Pipeline 并行运行,通过 Pipeline-to-Pipeline 通信实现数据处理的分层和分流。
多 Pipeline 配置:
# pipelines.yml
- pipeline.id: input-layer
path.config: "/etc/logstash/conf.d/inputs/*.conf"
pipeline.workers: 4
pipeline.batch.size: 125
- pipeline.id: filter-layer
path.config: "/etc/logstash/conf.d/filters/*.conf"
pipeline.workers: 8
pipeline.batch.size: 500
- pipeline.id: output-layer
path.config: "/etc/logstash/conf.d/outputs/*.conf"
pipeline.workers: 4
pipeline.batch.size: 250
- pipeline.id: dead-letter
path.config: "/etc/logstash/conf.d/dead_letter.conf"
pipeline.workers: 1
Pipeline-to-Pipeline 通信:
Input Pipeline (input-layer)
│
pipeline 发送端(send to)
│
↓ ↓ ↓
Filter Filter Dead Letter
Pipeline Pipeline Pipeline
(f1) (f2) (dlq)
│
pipeline 接收端(receive from)
│
Output Pipeline (output-layer)
发送端配置:
# input-layer.conf
input {
beats {
port => 5044
tags => ["nginx"]
}
kafka {
topics => ["app-logs"]
tags => ["app"]
}
}
output {
# 发送到 filter-layer pipeline
pipeline {
send_to => "filter-layer"
}
}
接收端配置:
# filter-layer.conf
input {
pipeline {
address => "filter-layer"
}
}
filter {
if "nginx" in [tags] {
grok { match => { "message" => "%{COMBINEDAPACHELOG}" } }
}
if "app" in [tags] {
json { source => "message" }
}
}
output {
pipeline { send_to => "output-layer" }
}
多 Pipeline 适用场景:
| 场景 | 方案 | 优势 |
|---|---|---|
| 多数据源隔离 | 各源独立 Pipeline | 故障隔离、独立优化 |
| 分层处理 | Input/Filter/Output 分离 | 各层可独立调配资源 |
| 灾备双活 | 双集群多 Pipeline | 并行处理、互不影响 |
| 死信处理 | 独立的 DLQ Pipeline | 不影响主线流程 |
33 Elasticsearch 的 Data Stream 和索引别名(Alias)管理如何用于日志场景?
答案:
Data Stream 是 7.9+ 引入的专门用于时间序列数据(日志、指标、事件)的存储抽象层,内部基于索引别名 + ILM 自动管理。
Data Stream vs Alias:
| 维度 | Data Stream | Index Alias |
|---|---|---|
| 自动管理 | 自动创建后备索引 | 需手动管理 |
| 写入 | 仅写入最新后备索引 | 可配置写入索引 |
| 查询 | 跨所有后备索引 | 跨多个索引 |
| ILM | 内置集成 | 需手动配置 |
| 映射变更 | 自动更新 | 手动更新 |
| 推荐场景 | 日志/指标/事件 | 通用别名场景 |
Data Stream 工作流:
写入请求 → Data Stream (logs-nginx)
│
后备索引列表
│
logs-nginx-000001 (Hot)
logs-nginx-000002 (Hot) ← 写入目标
logs-nginx-000003 (Warm)
logs-nginx-000004 (Cold)
│
写入流最新后备索引
创建与使用:
// 1. 创建索引模板(启用 Data Stream)
PUT /_index_template/nginx-logs-stream
{
"index_patterns": ["logs-nginx-*"],
"data_stream": {},
"priority": 500,
"template": {
"settings": {
"number_of_shards": 3,
"number_of_replicas": 1
},
"mappings": {
"properties": {
"@timestamp": { "type": "date" },
"message": { "type": "text" },
"request.path": { "type": "keyword" }
}
}
}
}
// 2. 创建 Data Stream(写入即自动创建)
POST /logs-nginx/_doc
{
"@timestamp": "2026-05-26T10:00:00Z",
"message": "GET /api/users 200",
"request": { "path": "/api/users" }
}
// 3. 查询 Data Stream
GET /logs-nginx/_search
// 4. 查看后备索引
GET /_data_stream/logs-nginx
// 5. 手动滚动
POST /logs-nginx/_rollover
Index Alias 对比:
// Alias 传统方式
POST /_aliases
{
"actions": [
{ "add": { "index": "logs-nginx-2026.05.26", "alias": "logs-nginx" } }
]
}
// Data Stream 自动管理
// 无需手动维护 alias 和索引创建
Data Stream 最佳实践:
监控 Data Stream 大小和数量
GET /_data_stream
→ 每个 Data Stream 后备索引数 < 500
ILM + Data Stream 无缝集成
PUT /_ilm/policy/logs_policy
→ rollover + warm + cold + delete
故障恢复
后备索引损坏 → reindex 到新 Data Stream
34 Elastic Stack 的 Elastic Agent 和 Fleet Server 架构是如何工作的?和传统 Beats 模式有何不同?
答案:
Elastic Agent + Fleet Server 是 Elastic 7.10+ 引入的新一代数据采集架构,统一管理所有 Agent。
架构对比:
graph TD
subgraph 传统模式
FA["Filebeat Agent"] --> Config["各自配置"] --> LS1["Logstash"] --> ES1["ES"]
end
subgraph Agent_Fleet["Agent + Fleet 模式"]
FS["Fleet Server"] <-->|API| KB["Kibana (Fleet UI)"]
FS -->|管理策略下发| A1["Agent 1<br/>(logs)"]
FS -->|管理策略下发| A2["Agent 2<br/>(metrics)"]
FS -->|管理策略下发| AN["Agent N<br/>(security)"]
A1 --> LS2["Logstash / Elasticsearch"]
A2 --> LS2
AN --> LS2
end
Elastic Agent 优势:
| 维度 | Beats 模式 | Agent + Fleet |
|---|---|---|
| 管理方式 | 逐台配置管理 | 集中策略下发 |
| 集成种类 | 单 Beats 单用途 | 多集成同一 Agent |
| 升级 | 手动或编排 | Fleet 远程升级 |
| 安全 | 独立配置 | 统一证书管理 |
| 扩展性 | Filebeat/Metricbeat 等 | Agent + Integration |
Fleet Server 部署:
# fleet-server.yml
server:
host: 0.0.0.0
port: 8220
fleet:
# ES 连接
elasticsearch:
hosts: ["https://es-node:9200"]
service_token: "<token>"
# 策略配置
agent:
id: fleet-server-1
# TLS 配置
inputs:
- type: fleet-server
ssl:
enabled: true
certificate: /etc/fleet-server/certs/server.crt
key: /etc/fleet-server/certs/server.key
Agent 策略配置(Kibana Fleet UI):
# fleet 策略 → agent-policy-logs
inputs:
- type: logfile
streams:
- data_stream:
dataset: nginx.access
type: logs
paths:
- /var/log/nginx/access.log
exclude_files: [".gz$"]
multiline:
pattern: '^\d{4}-\d{2}-\d{2}'
negate: true
match: after
processors:
- add_host_metadata: ~
- add_cloud_metadata: ~
- type: system/metrics
streams:
- data_stream:
dataset: system.cpu
type: metrics
metricsets: [cpu]
period: 10s
迁移路径:
Filebeat + Metricbeat → 合并为单个 Elastic Agent
│
├── 使用 Agent 的内置集成(Nginx/Redis/MySQL)
├── 兼容 Beats 配置(部分)
└── Fleet Server 集中管理(≥ 10 台推荐)
35 ELK Stack 在生产环境中如何进行容量规划?
答案:
ELK Stack 的容量规划涵盖数据量估算、节点配置、存储方案和资源预留四个维度。
数据量估算模型:
每日原始日志量 = 日志产生速率(行/秒) × 平均单行大小 × 86400
每日存储量 = 原始日志量 × (1 + 索引开销系数)
索引开销系数:20-30%(_source、倒排索引、doc_values)
副本开销:× (1 + number_of_replicas)
示例:
速率:5000 行/秒 单行:512 bytes
每日原始 = 5000 × 512 × 86400 ≈ 206 GB/天
每日存储(1副本)= 206 × 1.3 × 2 ≈ 536 GB/天
30天保留 = 536 × 30 ≈ 16 TB
节点配置参考:
| 集群规模 | 每日数据量 | 数据节点 | 每节点配置 | Master 节点 |
|---|---|---|---|---|
| 小型 | < 100 GB | 3 | 16C / 32G RAM / 2TB SSD | 3(2C/4G) |
| 中型 | 100-500 GB | 5-9 | 32C / 64G RAM / 4TB SSD | 3(4C/8G) |
| 大型 | 500 GB-2 TB | 9-15 | 48C / 128G RAM / 8TB NVMe | 3(8C/16G) |
| 超大型 | > 2 TB | 15+ | 64C / 256G RAM / 15TB NVMe | 3(8C/32G) |
存储方案对比:
| 方案 | 成本 | 性能 | 管理复杂度 | 推荐场景 |
|---|---|---|---|---|
| 本地 NVMe SSD | 高 | 极高 | 低 | 高性能写入 |
| 本地 SATA SSD | 中 | 高 | 低 | 通用场景 |
| SAN/NAS | 高 | 中 | 高 | 已有基础设施 |
| S3 + ILM Cold | 低 | 低 | 中 | 冷数据归档 |
Logstash 容量:
单 Logstash 实例建议:
4-8 CPU cores
4-8 GB 堆内存
处理能力 ≈ 10k-50k events/s(取决于 filter 复杂度)
Kafka 作为缓冲层扩展:
Logstash Input → Kafka → Logstash Filter → ES
解耦采集和处理速度
Kibana 资源:
Kibana 实例:
最低 4GB 内存(推荐 8GB+)
多实例 + 负载均衡(高可用)
缓存大小可调:
kibana.max_old_space_size: 4096
kibana.max_old_space_size: 8192(大面板场景)
预留与预警策略:
| 资源 | 预留比例 | 预警线 | 操作 |
|---|---|---|---|
| 磁盘 | 80% 使用 | 75% | 扩展节点或清理 ILM |
| 堆内存 | 50% 物理 | 75% | 扩容或优化查询 |
| CPU | 70% | 85% | 扩容协调节点 |
| 网络带宽 | 60% | 80% | 升级网络或压缩 |