HDFS集群缩容案例: Decommission DataNode
导语
在HDFS集群运维过程中,常会碰到因为实际业务增长低于集群创建时的预估规模;集群数据迁出,数据节点冗余较多;费用控制等原因,需要对集群进行缩容操作。Decommission DataNode是该过程中关键的一步,就是把DataNode从集群中移除掉。那问题来了,HDFS在设计时就把诸如机器故障考虑进去了,能否直接把某台运行Datanode的机器关掉然后拔走呢?理论上可行的,不过在实际的集群中,如果某份数据只有一份副本而且它就在这个机器上,那么直接关掉并拔走机器就会造成数据丢失。本文将介绍如何Decommission DataNode以及可能会遇到Decommission超时案例及其解决方案。
Decommission DataNode步骤
1、在Active Namenode节点,把需要Decommission的DataNode的主机名加入到dfs.hosts.exclude(该配置项在hdfs-site.xml)所指定的文件中,有多个Decommission DataNode以换行分割,建议一次Decommission节点小于hdfs备份数。腾讯云EMR该文件为/usr/local/service/hadoop/etc/hadoop/hdfsexcludedhosts。
PS:如果hdfs-site.xml中未找到dfs.hosts.exclude,需手动将该属性加入配置文件中,如:
<property>
<name>dfs.hosts.exclude</name>
<value>/usr/local/service/hadoop/etc/hadoop/hdfsexcludedhosts</value>
</property>
2、在Active NameNode节点,执行以下命令:su <HDFS_USER> hdfs dfsadmin -refreshNodes。<HDFS_USER>指的是拥有HDFS服务的用户,腾讯云EMR为hadoop。
3、打开NameNode Web UI,跳转到Datanodes页面,检查要Decommission的DataNode的状态是否已更改为“Decommission In Progress”,如下图。
4、当Decommission DataNode节点所有块均已复制,其状态将变为“Decommissioned”,如下图。
5、在Decommission DataNode节点停止DataNode进程,执行以下命令<HADOOP_HOME>/sbin/hadoop-daemon.sh stop datanode。腾讯云EMR直接在控制台操作。
6、在Active NameNode主机上,清空<步骤1>中文件添加的Decommission节点的主机名,然后执行以下命令:su <HDFS_USER> hdfs dfsadmin -refreshNodes。<HDFS_USER>指的是拥有HDFS服务的用户,腾讯云EMR为hadoop。
案例
问题描述
客户反馈,正常3个节点,一天就可以完成下线,这次执行了5天还没完成,并不是不动,而是动的非常慢
原因分析
查看NameNode Web UI的Datanodes页面如下
- Under replicated blocks:当前block的副本 < 所设置的副本(默认就是小于3) 数量
- Blocks with no live replicas:没有live 的副本,存在的副本可能都在Decommission的节点上
- Under Replicated Blocks In files under construction: 当前正在复制中的block个数
在decommission几个节点中,存在副本只在Decommission的节点上的情况。这意味着,如果“删除”数据节点,则带有这些块的文件将被损坏。以防这种现象出现,Decommission节点会被阻塞。
解决方案
检查0/1/2副本的文件,强制改成三副本
1、打印所有块信息:
hdfs fsck / -files -blocks > ./blocks.txt
2、检查副本:
sed '$!N;/Live_repl=0/P;D' ./blocks.txt | grep "block" | awk '{print $1}' > ./rep_0.txt # 0副本文件
sed '$!N;/Live_repl=1/P;D' ./blocks.txt | grep "block" | awk '{print $1}' > ./rep_1.txt # 1副本文件
sed '$!N;/Live_repl=2/P;D' ./blocks.txt | grep "block" | awk '{print $1}' > ./rep_2.txt # 2副本文件
3、改副本数:(改之前确认一下文件内容)
for hdfsfile in `cat ./rep_0.txt`; do hdfs dfs -setrep 3 $hdfsfile; done
for hdfsfile in `cat ./rep_1.txt`; do hdfs dfs -setrep 3 $hdfsfile; done
for hdfsfile in `cat ./rep_2.txt`; do hdfs dfs -setrep 3 $hdfsfile; done
延申
1、文件未关闭导致Decommission超时
当待Decommission DataNode节点中存在打开中的文件,表明此文件目前不是一个完整状态,此文件副本就无法复制到其它datanode节点上,由于存在未完全复制完的副本,则待Decommission会被阻塞超时。通过以下步骤检查Decommission 节点是否存在打开的文件。
检查日志获取正在退服的块
grep "Is current datanode" hadoop-xx-namenode-xxxxxxxxx.log | tail | awk '{print $9}'
根据block id 获取对应的文件,并检查是否处于打开状态
hdfs fsck -blockId block_id
hadoop fsck 文件名 -files -blocks -locations -openforwrite
2、调整参数加速Decommission DataNode
Decommission DataNode相关参数
参数名称 |
默认值 |
参数含义 |
---|---|---|
dfs.namenode.decommission.interval |
30 |
每次启动monitor线程处理退服节点的间隔 |
dfs.namenode.decommission.blocks.per.interval |
500000 |
每个批次最多处理多少个文件块 |
dfs.namenode.decommission.max.concurrent.tracked.nodes |
100 |
同时处理退服的节点个数 |
dfs.namenode.replication.work.multiplier.per.iteration |
32 |
每次复制的块的个数为 dn的个数* 该参数 |
dfs.namenode.replication.max-streams |
64 |
进行复制任务分配时,单个DN 任务的最大值 |
dfs.namenode.replication.max-streams-hard-limit |
128 |
若DN 的复制任务大于改值时,不会将其选为复制的源节点 |
默认参数下,Decommission执行速度较慢,建议检查参数是否为建议值,可适当调大下列参数
dfs.namenode.replication.work.multiplier.per.iteration 注意:过大会导致块复制操作占用过多的带宽,影响业务
dfs.namenode.replication.max-streams
dfs.namenode.replication.max-streams-hard-limit
- ios tableview 上加 textfiled
- Spring Cloud实战小贴士:Feign的继承特性(伪RPC模式)
- 仿淘宝购买详情页购买缩小动画
- 高仿今日头条(1)
- android Native堆
- Spring Boot中Web应用的统一异常处理
- android bitmap的内存分配和优化
- Gitflow工作流程
- Android学习第一弹:Android通过用代码画虚线椭圆边框背景来学习一下shape的用法
- Spring Boot中使用Swagger2构建强大的RESTful API文档
- iOS iOS与html进行交互
- Android学习第三弹之Android图片颜色处理
- C#Winform使用扩展方法自定义富文本框(RichTextBox)字体颜色
- Android如何实现毛玻璃效果之Android高级模糊技术
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- PHP pthreads v3下worker和pool的使用方法示例
- 浅谈python脚本设置运行参数的方法
- laravel框架实现敏感词汇过滤功能示例
- python 接收处理外带的参数方法
- Django框架实现的简单分页功能示例
- php测试kafka项目示例
- Python读取YUV文件,并显示的方法
- php-7.3.6 编译安装过程
- PHP查找一列有序数组是否包含某值的方法
- python 从文件夹抽取图片另存的方法
- laravel框架使用极光推送消息操作示例
- 对pycharm 修改程序运行所需内存详解
- Python小工具之消耗系统指定大小内存的方法
- Thinkphp框架+Layui实现图片/文件上传功能分析
- PHP实现单例模式建立数据库连接的方法分析