一、前言:生产环境的噩梦
1.1 你可能遇到过这些问题
graph TD
A[凌晨告警] --> B["Checkpoint 失败"]
A --> C["背压严重"]
A --> D["OOM 崩溃"]
A --> E["数据延迟"]
A --> F["作业重启"]
B & C & D & E & F --> G["你:😭"]
1.2 本文内容
mindmap
root((Flink调优))
资源调优
内存配置
并行度设置
Slot分配
Checkpoint调优
间隔与超时
增量CP
状态后端
背压处理
识别瓶颈
优化方案
常见问题
OOM排查
数据倾斜
延迟问题
二、资源配置调优
2.1 内存模型
graph TB
subgraph "TaskManager 内存模型"
TOTAL[Total Process Memory] --> FLINK[Flink Memory]
TOTAL --> JVM_META[JVM Metaspace]
TOTAL --> JVM_OVER[JVM Overhead]
FLINK --> FRAMEWORK[Framework Heap
框架堆内存] FLINK --> TASK[Task Heap
任务堆内存] FLINK --> MANAGED[Managed Memory
托管内存] FLINK --> NETWORK[Network Memory
网络缓冲] MANAGED --> M1["RocksDB
批处理排序"] end
框架堆内存] FLINK --> TASK[Task Heap
任务堆内存] FLINK --> MANAGED[Managed Memory
托管内存] FLINK --> NETWORK[Network Memory
网络缓冲] MANAGED --> M1["RocksDB
批处理排序"] end
2.2 内存配置
# flink-conf.yaml 内存配置
# TaskManager 总内存
taskmanager.memory.process.size: 8g
# 或者只配置 Flink 内存
taskmanager.memory.flink.size: 6g
# 细粒度配置
taskmanager.memory.framework.heap.size: 128m # 框架堆内存
taskmanager.memory.task.heap.size: 2g # 任务堆内存
taskmanager.memory.managed.size: 2g # 托管内存(RocksDB)
taskmanager.memory.network.min: 256m # 网络缓冲最小
taskmanager.memory.network.max: 1g # 网络缓冲最大
taskmanager.memory.network.fraction: 0.1 # 网络缓冲占比
# JVM 配置
taskmanager.memory.jvm-metaspace.size: 256m # 元空间
taskmanager.memory.jvm-overhead.min: 256m # JVM开销最小
taskmanager.memory.jvm-overhead.max: 1g # JVM开销最大
taskmanager.memory.jvm-overhead.fraction: 0.1 # JVM开销占比
# JobManager 内存
jobmanager.memory.process.size: 2g2.3 内存配置建议
flowchart TD
A[内存配置决策] --> B{使用 RocksDB?}
B -->|是| C["增加 Managed Memory
建议 2-4G"] B -->|否| D["Managed Memory 可以小
默认即可"] A --> E{网络密集型?} E -->|是| F["增加 Network Memory
建议 10-15%"] E -->|否| G["默认 10% 即可"] A --> H{状态很大?} H -->|是| I["使用 RocksDB
增加磁盘 IOPS"] H -->|否| J["HashMapStateBackend
增加 Task Heap"]
建议 2-4G"] B -->|否| D["Managed Memory 可以小
默认即可"] A --> E{网络密集型?} E -->|是| F["增加 Network Memory
建议 10-15%"] E -->|否| G["默认 10% 即可"] A --> H{状态很大?} H -->|是| I["使用 RocksDB
增加磁盘 IOPS"] H -->|否| J["HashMapStateBackend
增加 Task Heap"]
2.4 并行度设置
// 并行度设置原则
// 1. 全局并行度 = TaskManager 数量 × 每个 TM 的 Slot 数
env.setParallelism(totalSlots);
// 2. Source 并行度 = Kafka 分区数
source.setParallelism(kafkaPartitions);
// 3. Sink 并行度根据目标系统承受能力
sink.setParallelism(targetCapacity);
// 4. 计算密集型算子可以适当提高
heavyOperator.setParallelism(env.getParallelism() * 2);并行度配置建议:
| 场景 | 建议 |
|---|---|
| Kafka Source | = Kafka 分区数 |
| 普通算子 | = 全局并行度 |
| CPU 密集型 | 可适当增加 |
| IO 密集型 | 可适当增加 |
| Sink | 根据目标系统调整 |
三、Checkpoint 调优
3.1 Checkpoint 配置
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
// 启用 Checkpoint
env.enableCheckpointing(60000); // 60秒间隔
CheckpointConfig config = env.getCheckpointConfig();
// 1. 语义模式
config.setCheckpointingMode(CheckpointingMode.EXACTLY_ONCE);
// 2. 超时时间
config.setCheckpointTimeout(600000); // 10分钟
// 3. 最小间隔
config.setMinPauseBetweenCheckpoints(30000); // 30秒
// 4. 并发 Checkpoint 数
config.setMaxConcurrentCheckpoints(1);
// 5. 容忍失败次数
config.setTolerableCheckpointFailureNumber(3);
// 6. 取消作业时保留 Checkpoint
config.setExternalizedCheckpointCleanup(
ExternalizedCheckpointCleanup.RETAIN_ON_CANCELLATION
);
// 7. Checkpoint 存储
config.setCheckpointStorage("hdfs:///flink/checkpoints");
// 8. 非对齐 Checkpoint (Flink 1.11+)
config.enableUnalignedCheckpoints();
// 9. 对齐超时
config.setAlignedCheckpointTimeout(Duration.ofMinutes(1));3.2 增量 Checkpoint
# 使用 RocksDB + 增量 Checkpoint
state.backend: rocksdb
state.backend.incremental: true
state.checkpoints.dir: hdfs:///flink/checkpoints
state.savepoints.dir: hdfs:///flink/savepoints
# RocksDB 配置
state.backend.rocksdb.localdir: /ssd/rocksdb
state.backend.rocksdb.memory.managed: true
state.backend.rocksdb.checkpoint.transfer.thread.num: 4graph LR
subgraph "全量 Checkpoint"
F1[每次保存全部状态]
F2[状态大时耗时长]
end
subgraph "增量 Checkpoint"
I1[只保存变化部分]
I2[速度快]
I3[仅 RocksDB 支持]
end
3.3 Checkpoint 失败排查
flowchart TD
A[Checkpoint 失败] --> B{错误类型}
B -->|超时| C["检查:
1. 状态大小
2. 存储写入速度
3. Barrier 对齐"] C --> C1["解决:
1. 增加超时时间
2. 使用增量CP
3. 开启非对齐CP"] B -->|存储异常| D["检查:
1. HDFS/S3 连接
2. 权限问题
3. 空间不足"] D --> D1["解决:
1. 检查网络
2. 检查权限
3. 清理空间"] B -->|状态序列化失败| E["检查:
1. 状态类型
2. 序列化器"] E --> E1["解决:
1. 检查类定义
2. 配置序列化器"]
1. 状态大小
2. 存储写入速度
3. Barrier 对齐"] C --> C1["解决:
1. 增加超时时间
2. 使用增量CP
3. 开启非对齐CP"] B -->|存储异常| D["检查:
1. HDFS/S3 连接
2. 权限问题
3. 空间不足"] D --> D1["解决:
1. 检查网络
2. 检查权限
3. 清理空间"] B -->|状态序列化失败| E["检查:
1. 状态类型
2. 序列化器"] E --> E1["解决:
1. 检查类定义
2. 配置序列化器"]
3.4 Checkpoint 监控指标
| 指标 | 含义 | 告警阈值 |
|---|---|---|
lastCheckpointDuration | 最近CP耗时 | > 1分钟 |
lastCheckpointSize | 最近CP大小 | 持续增长 |
numberOfCompletedCheckpoints | 完成数 | - |
numberOfFailedCheckpoints | 失败数 | > 0 |
lastCheckpointAlignmentDuration | 对齐耗时 | > 10秒 |
四、背压问题排查
4.1 什么是背压?
sequenceDiagram
participant Source
participant Operator
participant Sink
Source->>Operator: 数据
Note over Operator: 处理能力 100/s
Operator->>Sink: 数据
Note over Sink: 处理能力 50/s
Sink-->>Operator: Buffer 满
Note over Operator: 背压!
Operator-->>Source: Buffer 满
Note over Source: 背压!
4.2 背压识别
graph TB
subgraph "Web UI 背压状态"
OK["OK (绿色)
正常"] LOW["LOW (黄色)
轻微背压"] HIGH["HIGH (红色)
严重背压"] end subgraph "指标" A["backPressuredTimeMsPerSecond"] B["idleTimeMsPerSecond"] C["busyTimeMsPerSecond"] end
正常"] LOW["LOW (黄色)
轻微背压"] HIGH["HIGH (红色)
严重背压"] end subgraph "指标" A["backPressuredTimeMsPerSecond"] B["idleTimeMsPerSecond"] C["busyTimeMsPerSecond"] end
背压定位步骤:
1. 打开 Web UI -> 作业 -> 选择 Task
2. 查看各 SubTask 的背压状态
3. 找到第一个出现 HIGH 的算子
4. 该算子的下游就是瓶颈所在4.3 背压原因与解决
flowchart TD
A[背压原因] --> B[下游处理慢]
A --> C[资源不足]
A --> D[数据倾斜]
A --> E[外部系统慢]
B --> B1["优化算子逻辑
增加并行度"] C --> C1["增加 TaskManager
增加内存"] D --> D1["打散热点 Key
两阶段聚合"] E --> E1["批量写入
异步IO"]
增加并行度"] C --> C1["增加 TaskManager
增加内存"] D --> D1["打散热点 Key
两阶段聚合"] E --> E1["批量写入
异步IO"]
4.4 常见背压场景处理
场景1:Sink 写入慢
// 原因:同步写入,一条一条写
// 解决:批量写入
// 使用 Async I/O
AsyncDataStream.unorderedWait(
stream,
new AsyncDatabaseRequest(),
1000, // 超时
TimeUnit.MILLISECONDS,
100 // 最大并发请求
);
// 使用批量 Sink
JdbcSink.sink(
"INSERT INTO table VALUES (?, ?)",
(ps, record) -> { ... },
JdbcExecutionOptions.builder()
.withBatchSize(1000) // 批量大小
.withBatchIntervalMs(200) // 批量间隔
.withMaxRetries(3)
.build(),
...
);场景2:窗口数据量大
// 原因:窗口积累太多数据
// 解决:使用增量聚合
// ❌ 错误:使用 ProcessWindowFunction 存储所有数据
.window(TumblingEventTimeWindows.of(Time.hours(1)))
.process(new ProcessWindowFunction<>() { ... });
// ✅ 正确:使用增量聚合
.window(TumblingEventTimeWindows.of(Time.hours(1)))
.aggregate(
new MyAggregateFunction(), // 增量聚合
new MyProcessWindowFunction() // 只获取窗口信息
);场景3:数据倾斜
// 原因:某个 Key 数据量特别大
// 解决:两阶段聚合
// 第一阶段:加盐打散
DataStream<Tuple2<String, Long>> salted = stream
.map(event -> {
String saltedKey = event.getKey() + "_" + (event.hashCode() % 10);
return Tuple2.of(saltedKey, event.getValue());
})
.keyBy(t -> t.f0)
.window(TumblingEventTimeWindows.of(Time.minutes(1)))
.sum(1);
// 第二阶段:去盐聚合
DataStream<Tuple2<String, Long>> result = salted
.map(t -> {
String originalKey = t.f0.substring(0, t.f0.lastIndexOf("_"));
return Tuple2.of(originalKey, t.f1);
})
.keyBy(t -> t.f0)
.window(TumblingEventTimeWindows.of(Time.minutes(1)))
.sum(1);五、OOM 问题排查
5.1 Flink OOM 类型
graph TB
A[Flink OOM] --> B["Java Heap OOM
堆内存溢出"] A --> C["Direct Memory OOM
直接内存溢出"] A --> D["Metaspace OOM
元空间溢出"] A --> E["Container Killed
容器被杀"] B --> B1["状态太大
用户代码问题"] C --> C1["网络缓冲不足
RocksDB问题"] D --> D1["类加载太多"] E --> E1["超出容器限制"]
堆内存溢出"] A --> C["Direct Memory OOM
直接内存溢出"] A --> D["Metaspace OOM
元空间溢出"] A --> E["Container Killed
容器被杀"] B --> B1["状态太大
用户代码问题"] C --> C1["网络缓冲不足
RocksDB问题"] D --> D1["类加载太多"] E --> E1["超出容器限制"]
5.2 OOM 排查步骤
flowchart TD
A[OOM 发生] --> B{哪种 OOM?}
B -->|Java Heap| C["1. 检查状态大小
2. 检查用户代码
3. 增加 Task Heap"] B -->|Direct Memory| D["1. 增加 Network Memory
2. 检查 RocksDB 配置
3. 减少并行度"] B -->|Metaspace| E["1. 增加 Metaspace
2. 检查 ClassLoader"] B -->|Container Killed| F["1. 检查 JVM Overhead
2. 增加容器内存
3. 检查 Native 内存"]
2. 检查用户代码
3. 增加 Task Heap"] B -->|Direct Memory| D["1. 增加 Network Memory
2. 检查 RocksDB 配置
3. 减少并行度"] B -->|Metaspace| E["1. 增加 Metaspace
2. 检查 ClassLoader"] B -->|Container Killed| F["1. 检查 JVM Overhead
2. 增加容器内存
3. 检查 Native 内存"]
5.3 OOM 配置解决
# Java Heap OOM
taskmanager.memory.task.heap.size: 4g
# Direct Memory OOM
taskmanager.memory.network.min: 512m
taskmanager.memory.network.max: 2g
taskmanager.memory.framework.off-heap.size: 128m
# Metaspace OOM
taskmanager.memory.jvm-metaspace.size: 512m
# Container Killed
taskmanager.memory.jvm-overhead.min: 512m
taskmanager.memory.jvm-overhead.max: 2g
taskmanager.memory.jvm-overhead.fraction: 0.155.4 堆内存分析
# 开启 OOM 时 Heap Dump
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/tmp/flink-heap-dump.hprof
# 配置方式
env.java.opts.taskmanager: "-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp/"
# 分析工具
# 1. Eclipse MAT (Memory Analyzer Tool)
# 2. VisualVM
# 3. JProfiler六、数据延迟问题
6.1 延迟来源
graph LR
A[数据产生] -->|延迟1| B[数据采集]
B -->|延迟2| C[消息队列]
C -->|延迟3| D[Flink处理]
D -->|延迟4| E[结果输出]
subgraph "端到端延迟"
A --> E
end
6.2 延迟监控
// 配置延迟追踪
env.getConfig().setLatencyTrackingInterval(1000); // 1秒采样
// 指标
// flink_taskmanager_job_latency_source_id_operator_id_operator_subtask_index_latency6.3 延迟优化
mindmap
root((降低延迟))
Source端
减少批量大小
增加拉取频率
处理端
减少窗口大小
使用ProcessingTime
优化算子逻辑
Sink端
异步写入
减少批量大小
资源
增加并行度
使用SSD
具体优化措施:
// 1. Kafka Source 优化
KafkaSource.<String>builder()
.setProperty("fetch.max.wait.ms", "100") // 减少等待时间
.setProperty("fetch.min.bytes", "1") // 减少最小拉取大小
.build();
// 2. 减少缓冲
env.setBufferTimeout(10); // 10ms 刷新缓冲
// 3. 使用处理时间(牺牲准确性换速度)
.window(TumblingProcessingTimeWindows.of(Time.seconds(10)))
// 4. 异步 Sink
AsyncDataStream.unorderedWait(
stream,
new AsyncSinkFunction(),
100, // 超时 ms
TimeUnit.MILLISECONDS
);七、常用调优参数汇总
7.1 flink-conf.yaml 生产配置
#==============================================================================
# 基础配置
#==============================================================================
jobmanager.rpc.address: flink-jobmanager
jobmanager.rpc.port: 6123
jobmanager.bind-host: 0.0.0.0
#==============================================================================
# JobManager 内存
#==============================================================================
jobmanager.memory.process.size: 4g
jobmanager.memory.jvm-metaspace.size: 256m
jobmanager.memory.jvm-overhead.min: 256m
jobmanager.memory.jvm-overhead.max: 512m
#==============================================================================
# TaskManager 内存
#==============================================================================
taskmanager.memory.process.size: 8g
taskmanager.memory.task.heap.size: 2g
taskmanager.memory.managed.size: 2g
taskmanager.memory.network.min: 512m
taskmanager.memory.network.max: 1g
taskmanager.memory.jvm-metaspace.size: 256m
taskmanager.memory.jvm-overhead.min: 512m
taskmanager.memory.jvm-overhead.max: 1g
#==============================================================================
# 并行度与 Slot
#==============================================================================
parallelism.default: 4
taskmanager.numberOfTaskSlots: 4
#==============================================================================
# Checkpoint 配置
#==============================================================================
execution.checkpointing.interval: 60000
execution.checkpointing.mode: EXACTLY_ONCE
execution.checkpointing.timeout: 600000
execution.checkpointing.min-pause: 30000
execution.checkpointing.max-concurrent-checkpoints: 1
execution.checkpointing.tolerable-failed-checkpoints: 3
execution.checkpointing.externalized-checkpoint-retention: RETAIN_ON_CANCELLATION
execution.checkpointing.unaligned: true
#==============================================================================
# 状态后端
#==============================================================================
state.backend: rocksdb
state.backend.incremental: true
state.checkpoints.dir: hdfs:///flink/checkpoints
state.savepoints.dir: hdfs:///flink/savepoints
# RocksDB 配置
state.backend.rocksdb.localdir: /ssd/rocksdb
state.backend.rocksdb.memory.managed: true
state.backend.rocksdb.checkpoint.transfer.thread.num: 4
state.backend.rocksdb.writebuffer.count: 4
state.backend.rocksdb.writebuffer.size: 64mb
#==============================================================================
# 高可用
#==============================================================================
high-availability: zookeeper
high-availability.zookeeper.quorum: zk1:2181,zk2:2181,zk3:2181
high-availability.zookeeper.path.root: /flink
high-availability.cluster-id: /cluster-1
high-availability.storageDir: hdfs:///flink/ha
#==============================================================================
# 网络
#==============================================================================
taskmanager.network.memory.buffer-debloat.enabled: true
taskmanager.network.memory.buffer-debloat.period: 200ms
#==============================================================================
# 其他
#==============================================================================
rest.port: 8081
web.submit.enable: true
classloader.resolve-order: parent-first7.2 常用 JVM 参数
# TaskManager JVM 参数
env.java.opts.taskmanager: >-
-XX:+UseG1GC
-XX:MaxGCPauseMillis=200
-XX:+PrintGCDetails
-XX:+PrintGCDateStamps
-Xloggc:/opt/flink/log/gc.log
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/opt/flink/log/
# JobManager JVM 参数
env.java.opts.jobmanager: >-
-XX:+UseG1GC
-XX:MaxGCPauseMillis=200八、监控与告警
8.1 关键监控指标
graph TB
subgraph "作业健康度"
A1[numRestarts
重启次数] A2[uptime
运行时长] A3[fullRestarts
完全重启] end subgraph "吞吐量" B1[numRecordsInPerSecond
输入速率] B2[numRecordsOutPerSecond
输出速率] B3[numBytesInPerSecond
字节速率] end subgraph "延迟" C1[currentInputWatermark
当前水印] C2[latency
处理延迟] end subgraph "Checkpoint" D1[lastCheckpointDuration
CP耗时] D2[lastCheckpointSize
CP大小] D3[numberOfFailedCheckpoints
失败次数] end subgraph "背压" E1[backPressuredTimeMsPerSecond
背压时间] E2[busyTimeMsPerSecond
繁忙时间] end
重启次数] A2[uptime
运行时长] A3[fullRestarts
完全重启] end subgraph "吞吐量" B1[numRecordsInPerSecond
输入速率] B2[numRecordsOutPerSecond
输出速率] B3[numBytesInPerSecond
字节速率] end subgraph "延迟" C1[currentInputWatermark
当前水印] C2[latency
处理延迟] end subgraph "Checkpoint" D1[lastCheckpointDuration
CP耗时] D2[lastCheckpointSize
CP大小] D3[numberOfFailedCheckpoints
失败次数] end subgraph "背压" E1[backPressuredTimeMsPerSecond
背压时间] E2[busyTimeMsPerSecond
繁忙时间] end
8.2 Prometheus + Grafana 监控
# flink-conf.yaml
metrics.reporters: prometheus
metrics.reporter.prometheus.class: org.apache.flink.metrics.prometheus.PrometheusReporter
metrics.reporter.prometheus.port: 92498.3 告警规则
# Prometheus 告警规则示例
groups:
- name: flink_alerts
rules:
# 作业重启告警
- alert: FlinkJobRestarted
expr: increase(flink_jobmanager_job_numRestarts[5m]) > 0
for: 1m
labels:
severity: warning
annotations:
summary: "Flink 作业重启"
# Checkpoint 失败告警
- alert: FlinkCheckpointFailed
expr: increase(flink_jobmanager_job_numberOfFailedCheckpoints[5m]) > 0
for: 1m
labels:
severity: critical
annotations:
summary: "Checkpoint 失败"
# 背压告警
- alert: FlinkBackPressure
expr: flink_taskmanager_job_task_backPressuredTimeMsPerSecond > 500
for: 5m
labels:
severity: warning
annotations:
summary: "检测到背压"
# 延迟告警
- alert: FlinkHighLatency
expr: flink_taskmanager_job_task_latency > 60000
for: 5m
labels:
severity: warning
annotations:
summary: "处理延迟过高"九、问题排查清单
9.1 作业启动失败
flowchart TD
A[作业启动失败] --> B{错误类型}
B -->|ClassNotFound| C["检查依赖
检查 JAR 包"] B -->|资源不足| D["检查 Slot 数量
检查内存配置"] B -->|连接失败| E["检查网络
检查外部服务"] B -->|序列化错误| F["检查类定义
添加序列化器"]
检查 JAR 包"] B -->|资源不足| D["检查 Slot 数量
检查内存配置"] B -->|连接失败| E["检查网络
检查外部服务"] B -->|序列化错误| F["检查类定义
添加序列化器"]
9.2 作业运行异常
flowchart TD
A[运行异常] --> B{现象}
B -->|数据丢失| C["检查 Watermark
检查窗口配置
检查 allowedLateness"] B -->|数据重复| D["检查 Exactly-Once
检查 Sink 幂等性"] B -->|结果不对| E["检查时间语义
检查窗口逻辑"] B -->|性能下降| F["检查背压
检查数据倾斜"]
检查窗口配置
检查 allowedLateness"] B -->|数据重复| D["检查 Exactly-Once
检查 Sink 幂等性"] B -->|结果不对| E["检查时间语义
检查窗口逻辑"] B -->|性能下降| F["检查背压
检查数据倾斜"]
9.3 排查命令
# 查看作业列表
./bin/flink list
# 查看作业详情
./bin/flink info <job-id>
# 取消作业
./bin/flink cancel <job-id>
# 从 Savepoint 恢复
./bin/flink run -s hdfs:///savepoints/sp-xxx job.jar
# 查看日志
tail -f log/flink-*-taskmanager-*.log
# JVM 诊断
jstack <pid> # 线程堆栈
jmap -heap <pid> # 堆内存
jstat -gc <pid> # GC 统计十、最佳实践总结
10.1 生产环境 Checklist
□ 启用 Checkpoint,配置合理的间隔和超时
□ 使用 RocksDB + 增量 Checkpoint
□ 配置状态 TTL,避免状态无限增长
□ 所有算子设置 UID
□ 配置高可用 (ZooKeeper)
□ 配置监控和告警
□ 配置日志收集
□ 测试故障恢复
□ 准备扩缩容方案
□ 文档记录配置参数10.2 口诀总结
资源调优看内存,Heap/Network/Managed 分清楚
Checkpoint 要增量,RocksDB 后端是首选
背压问题找瓶颈,下游慢了要优化
OOM 问题分类型,堆内堆外要区分
监控告警要到位,及时发现早处理10.3 推荐配置
| 场景 | TaskManager 内存 | 并行度 | Checkpoint 间隔 |
|---|---|---|---|
| 小规模测试 | 2-4G | 1-4 | 60s |
| 中等生产 | 4-8G | 8-32 | 60s |
| 大规模生产 | 8-16G | 32-128 | 60-120s |
| 超大规模 | 16-32G | 128+ | 120-300s |
十一、总结
mindmap
root((Flink调优))
资源
内存配置
并行度
Slot
Checkpoint
间隔超时
增量CP
非对齐CP
性能
背压处理
数据倾斜
异步IO
稳定性
OOM处理
监控告警
故障恢复
调优核心原则:
- 先监控,后调优
- 找到瓶颈,针对性优化
- 小步迭代,验证效果
- 生产环境必须有监控和告警