大数据生产运维实战

一、HDFS 核心运维

1.1  集群存储状态快速诊断

 场景: 凌晨告警:HDFS 写入失败 / 磁盘告警 / DataNode 掉线,可用这组命令定位

 注意: Missing Blocks > 0 时立即停止写入相关目录,先执行 fsck 定位再决策;盲目重启会加重元数据损坏

# 1. 总览:DataNode 数量 / 可用空间 / 丢失块
hdfs dfsadmin -report | grep -E 'Live|Dead|Missing|DFS Used'

# 2. 文件系统完整性检查(有 Missing Block 立即执行)
hdfs fsck / -list-corruptfileblocks 2>/dev/null | head -30

# 3. 各 DataNode 磁盘使用详情
hdfs dfsadmin -report | awk '/^Name/{dn=$2} /Used/{print dn, $0}'

# 4. 查看 NameNode 内存(元数据对象数 × 150B ≈ NN 内存需求)
hdfs dfsadmin -report | grep 'Files and Directories'

1.2  磁盘空间告急处理(80% 阈值触发)

场景: DataNode 使用率 > 80%,HDFS 写入变慢;> 90% 触发 HDFS 只读保护

最佳实践: 生产建议:设置 dfs.datanode.du.reserved(预留 10% 磁盘给 OS),避免触发 OOM Killer

# 步骤1:定位最大目录
hdfs dfs -du -s -h /* | sort -rh | head -20

# 步骤2:检查 HDFS 回收站占用(大量旧数据可能在此)
hdfs dfs -du -s -h /user/*/. trash
hdfs dfs -expunge                           # 立即清空回收站

# 步骤3:降低非关键数据副本数(临时释放空间)
hdfs dfs -setrep -R -w 2 /warehouse/tmp    # 将副本从3改为2

# 步骤4:均衡数据(扩容后必做,避免新节点空闲)
hdfs balancer -threshold 10 &              # 后台运行,10%阈值

 1.3  NameNode 安全模式(Safe Mode)处理

场景: 集群重启后作业无法运行,HDFS 提示 'Name node is in safe mode'

说明: Safe Mode 触发条件:块可用率 < dfs.namenode.safemode.threshold-pct(默认0.999)。集群扩容后副本复制完成前会触发,属正常现象,等待即可

# 查看安全模式状态及块恢复进度
hdfs dfsadmin -safemode get
hdfs dfsadmin -report | grep 'Under replicated'

# 等块恢复完自动退出(正常情况);或手动强制退出(谨慎)
hdfs dfsadmin -safemode leave               # 仅在确认块完整后执行

1.4  NameNode HA 故障切换

场景: Active NameNode 进程崩溃 / 节点宕机,需要手动或自动切换到 Standby

注意: 强制切换前必须确认旧 Active 已完全停止(fencing),否则双 Active 会导致元数据脑裂,数据损坏无法恢复

# 查看当前 HA 状态
hdfs haadmin -getServiceState nn1
hdfs haadmin -getServiceState nn2

# 手动切换(原Active已彻底宕机的情况)
hdfs haadmin -failover --forcefence nn1 nn2

# 切换后验证
hdfs dfsadmin -report | head -5
hdfs haadmin -checkHealth nn2

1.5  数据误删除恢复

场景: 用户执行 hdfs dfs -rm -r 删除了重要数据,需要从回收站恢复

最佳实践: 对关键目录(如 Hive warehouse)启用快照保护:hdfs dfsadmin -allowSnapshot /warehouse && hdfs dfs -createSnapshot /warehouse daily_$(date +%Y%m%d)

# 查看回收站内容(回收站路径:/user/<username>/.Trash/Current/)
hdfs dfs -ls /user/hdfs/.Trash/Current/

# 恢复文件
hdfs dfs -mv /user/hdfs/.Trash/Current/warehouse/important /warehouse/important

# 如果回收站已清空,尝试从快照恢复
hdfs dfs -ls /data/.snapshot/                # 列出可用快照
hdfs dfs -cp /data/.snapshot/snap1/file /data/file   # 从快照恢复

 

二、YARN 资源与作业管理

2.1  资源配置黄金公式

场景: 新节点上线或内存告警时,快速计算 YARN 资源分配参数

注意: yarn.nodemanager.vmem-pmem-ratio 默认2.1,即申请1GB物理内存可用2.1GB虚拟内存。JVM GC行为可能导致虚拟内存超限被 Kill,生产建议设为2.5或关闭虚拟内存检查

参数 计算方法 128GB/32核示例

yarn.nodemanager.resource.memory-mb

总内存 - OS预留(8GB) - 其他服务(4GB)

116736 MB (~114GB)

yarn.nodemanager.resource.cpu-vcores

物理核数(超线程关闭时)或 核数×1.5

32 或 48

yarn.scheduler.minimum-allocation-mb

单Container最小内存,建议1024或2048

2048

yarn.scheduler.maximum-allocation-mb

单Container最大内存 ≤ NM总内存

32768 (32GB)

mapreduce.map.memory.mb

建议 minimum-allocation × 1

2048

mapreduce.reduce.memory.mb

建议 minimum-allocation × 2

4096

mapreduce.map.java.opts

container内存的75%(预留25%给JVM overhead)

-Xmx1536m

2.2  作业卡死 / 队列积压处理

场景: 作业长时间 ACCEPTED 状态、或某队列积压大量 Pending 作业

最佳实践: Capacity Scheduler 启用抢占(preemption):yarn.scheduler.capacity.preemption.enabled=true,防止低优先级队列长期占用高优先级队列资源

# 1. 查看当前所有运行/等待中的作业
yarn application -list -appStates RUNNING,ACCEPTED | head -30

# 2. 查看队列资源使用情况
yarn queue -status root.prod

# 3. 查看各节点状态(是否有不健康节点导致资源减少)
yarn node -list -states ALL | grep -v RUNNING

# 4. 快速定位占用资源最多的作业
yarn application -list -appStates RUNNING | sort -k8 -rn | head -10

# 5. Kill 占用过多资源的作业(协调业务方后执行)
yarn application -kill application_1234567890_0001

2.3  节点上下线操作(标准流程)

场景: DataNode / NodeManager 节点需要维护(系统升级、硬件更换)

注意: 切勿直接关机:未完成 decommission 直接断节点会导致 Under-replicated 甚至 Missing Blocks,副本恢复需消耗大量带宽

# 下线流程(3步,顺序执行):

# Step 1: 加入排除列表(graceful decommission)
echo 'worker-03.prod.com' >> $HADOOP_CONF_DIR/dfs.exclude
echo 'worker-03.prod.com' >> $HADOOP_CONF_DIR/yarn.exclude

# Step 2: 刷新配置(无需重启服务)
hdfs dfsadmin -refreshNodes
yarn rmadmin -refreshNodes

# Step 3: 等待 Decommissioned 完成(数据迁移中状态为 Decommission In Progress)
watch -n30 'hdfs dfsadmin -report | grep -A3 worker-03'
# 重新上线:
sed -i '/worker-03/d' $HADOOP_CONF_DIR/dfs.exclude
hdfs dfsadmin -refreshNodes && yarn rmadmin -refreshNodes

三、Spark 生产调优实战

3.1  Spark 作业提交标准模板

场景: 新作业上线,合理设置资源参数,避免资源浪费或不足

说明: num-executors × executor-cores = 总并行度基数。spark.default.parallelism 建议为总核数的 3-4 倍

# 生产推荐:yarn-cluster 模式(Driver 在集群内,Driver 挂了可自动重试)
spark-submit \
  --master yarn \
  --deploy-mode cluster \
  --name 'order_etl_daily' \
  --queue prod \                         # 指定队列,隔离资源
  --num-executors 20 \                   # Executor 数量
  --executor-cores 4 \                   # 每个Executor的核数(2-5之间)
  --executor-memory 8g \                 # Executor堆内存
  --conf spark.executor.memoryOverhead=1g \  # 堆外内存(≥ executor-memory × 10%)
  --conf spark.driver.memory=4g \
  --conf spark.driver.memoryOverhead=512m \
  --conf spark.default.parallelism=320 \ # 总核数(20×4=80) × 4
  --conf spark.sql.shuffle.partitions=320 \
  --conf spark.serializer=org.apache.spark.serializer.KryoSerializer \
  --conf spark.dynamicAllocation.enabled=false \ # 批处理建议固定资源
  myapp.jar

3.2  数据倾斜处理(最高频性能问题)

 场景: Spark 作业 99% Task 完成后某个 Task 卡很久,或 OOM 频繁发生在特定节点

注意: 不要用 repartition 解决倾斜(只是把数据洗牌,不改变 Key 分布)。spark.sql.shuffle.partitions 从默认200调大也无效,根因在于 Key 分布不均

# 诊断:打开 Spark UI → Stages → 看各 Task Duration 分布
# 诊断倾斜的 Key
df.groupBy('skew_key').count().orderBy(desc('count')).show(20)


# 方案一:加盐打散(彻底解决)
# 写入端:Key 加随机前缀
val salted = df.withColumn('salted_key',concat(col('key'), lit('_'), (rand() * 100).cast(IntegerType)))
# 读取端:去盐
val result = salted.withColumn('key', split(col('salted_key'), '_')(0))

# 方案二:Broadcast Join(小表 < 200MB 时优先用)
import org.apache.spark.sql.functions.broadcast
val result = bigDF.join(broadcast(smallDF), 'id')
// 调整 broadcast 阈值
spark.conf.set('spark.sql.autoBroadcastJoinThreshold', '209715200') // 200MB

# 方案三:分离热点 Key 单独处理
val hotKeys   = Seq('null', 'unknown', '')
val normalDF  = df.filter(!col('key').isin(hotKeys: _*))
val hotDF     = df.filter(col('key').isin(hotKeys: _*))
// hotDF 单独处理后 union

3.3  OOM 问题系统性排查

场景: Executor OOM 被 Kill / Driver OOM / Container 被 YARN 强制终止

OOM 类型

日志特征

解决方案

Executor Java Heap OOM

java.lang.OutOfMemoryError: Java heap space

增大 --executor-memory;减少数据 cache;检查是否有大对象

Executor 堆外内存溢出

Container killed by YARN for exceeding memory limits

增大 spark.executor.memoryOverhead(至少512m,建议 executor-memory×20%)

Driver OOM

java.lang.OutOfMemoryError in Driver

增大 --driver-memory;避免 collect() 大数据集到 Driver

GC Overhead

GC overhead limit exceeded

开启G1GC:-XX:+UseG1GC;减少对象创建;开启 Kryo 序列化

Shuffle OOM

spark.shuffle.* 相关 OOM

增大 spark.shuffle.memoryFraction;减少 shuffle 数据量

# 开启详细 GC 日志(排查 GC 问题)
--conf 'spark.executor.extraJavaOptions=-XX:+UseG1GC -XX:+PrintGCDetails -XX:+PrintGCDateStamps'

3.4  Spark 作业监控“三板斧”

场景: 如何快速判断一个 Spark 作业的性能瓶颈在哪里

① Spark Web UI(4040 / History Server 18080)关键页面:

  • Jobs 页:查看 Failed / Running Job,看总耗时分布
  • Stages 页:重点看 Shuffle Read/Write Size(大说明数据量多,考虑优化 Join)
  • Executors 页:看各 Executor GC Time(> 5% 说明 GC 严重)和 Task Time 是否均匀
  • SQL 页(Spark SQL):查看物理执行计划,找 SortMergeJoin(可优化为 BroadcastHashJoin)

② 日志快速查看

yarn logs -applicationId application_xxx -log_files stderr | grep -i 'error\|oom\|killed'

③ 历史作业对比分析

# Spark History Server REST API 查询作业耗时
curl http://history-server:18080/api/v1/applications?limit=20 | python -m json.tool

四、安全运维实战

4.1  Kerberos 日常维护

场景: 作业突然认证失败 / 凌晨定时任务认证过期

注意: 长时间 Spark 作业(> Kerberos Ticket 有效期)必须配置 keytab 自动续票,否则 Executor 在 Ticket 过期后无法访问 HDFS,作业静默失败

# 检查当前票据状态
klist -e                                     # 查看 TGT 有效期

# 服务账号(headless)使用 keytab 认证(生产定时任务标准写法)
kinit -kt /etc/security/keytabs/hdfs.keytab hdfs/$(hostname -f)@REALM.COM

# Spark 作业中内嵌认证(长时间运行作业)
spark-submit \
  --conf spark.yarn.keytab=/etc/security/keytabs/spark.keytab \
  --conf spark.yarn.principal=spark/host@REALM.COM \
  myapp.jar

# 强制续票(Ticket 快过期时)
kinit -R                                     # 续票(需 renewable 有效期内)

4.2  HDFS 权限快速配置

 场景: 新业务组入驻,需要创建目录并授权,多用户共享数据

最佳实践: 对敏感数据目录启用加密 Zone:hdfs crypto -createZone -keyName prod_key -path /warehouse/pii,数据静态加密,对上层应用透明

# 创建业务目录,设置组权限
hdfs dfs -mkdir -p /warehouse/team_a
hdfs dfs -chown -R hdfs:team_a /warehouse/team_a
hdfs dfs -chmod 775 /warehouse/team_a       # 组内可写,其他只读

# 使用 ACL 精细化授权(组无权限时追加特定用户)
hdfs dfs -setfacl -m user:alice:rwx /warehouse/team_a
hdfs dfs -setfacl -m user:bob:r-x  /warehouse/team_a
hdfs dfs -getfacl /warehouse/team_a         # 验证 ACL

# 设置目录配额,防止单业务占满空间
hdfs dfsadmin -setSpaceQuota 5t /warehouse/team_a    # 限制5TB
hdfs dfsadmin -setQuota 1000000 /warehouse/team_a   # 限制100万文件

五、数据管道运维实战

5.1  DistCp 集群间数据迁移

场景: 跨机房/集群迁移数据,或做数据备份

注意: 大规模迁移(TB级)必须设 -bandwidth 限速,否则会占满 DataNode 所有带宽,影响生产读写。推荐在业务低谷(凌晨2-6点)执行

# 基础迁移
hadoop distcp hdfs://src-cluster:8020/data/orders hdfs://dst-cluster:8020/data/orders

# 增量同步(只同步新增/修改文件)
hadoop distcp -update hdfs://src/data hdfs://dst/data

# 限速迁移(避免占满网络,单位 MB/s)
hadoop distcp -bandwidth 100 -m 20 hdfs://src/data hdfs://dst/data

# 保留文件权限/所有者/时间戳
hadoop distcp -pbugpt hdfs://src/data hdfs://dst/data

六、故障排查决策树

◈ 作业失败:首先看 YARN Web UI(8088) → application detail → 失败 Container 日志

◈ HDFS 写入失败:hdfs dfsadmin -report 看 DataNode 状态 → 看 NameNode 日志 → 检查磁盘

◈ 集群变慢:先 top 看 CPU/内存 → iostat 看 I/O → 再看 YARN 队列是否满负荷

◈ 认证失败:klist 检查票据 → kinit 重新认证 → 检查 KDC 服务状态

◈ 调度作业不触发:检查 Oozie 服务状态 → 检查 Coordinator 时区配置 → 检查输入数据是否就绪

 

Hadoop 核心原理: 从理论到实战

posted @ 2019-03-29 17:22  lvlin241  阅读(121)  评论(0)    收藏  举报