目录
一、节点掉线或退役
1.1区分节点掉线和节点退役的区别
1.2 如何处理节点掉线出现的各种风暴
1.2.1 Datanode的block复制
1.2.2 控制节点掉线RPC风暴的参数
二、如何快速节点下线
一、节点掉线或退役
背景:5台数据节点,存储40T数据 block数1120万块左右,集群带宽限制480GB/s,标准节点配置是12*8T,当前存储数据50-60TB,block 80万左右。
1.1区分节点掉线和节点退役的区别
节点退役:首先正常将节点加入退役名单,先告诉namenode和yarn不要在往上提交新任务和写入数据了;然后等待节点上的数据块在集群中复制完成;这个时候该退役的节点是优先作为srcNode数据源的(优先选择退役中的节点作为复制数据源src,因为其无写入请求,负载低),其他节点从该退役节点复制数据块到其他节点的,所以这个时候该节点的负载会很高。所有数据块复制完毕,节点状态变成Decommissioned,可以从、界面查看。注意数据节点退役数据开始复制的时间也是10分30s后,并不是因为是主动退役而提前,因为nannode和datanode永远都是维持着简单的主从关系,namenode节点不会主动向datanode节点发起任何IPC调用,datanode节点需要配合namenode完成的所有操作都是通过两者心跳应答时携带的DatanodeCommand返回的。
节点掉线:比如强制停止datanode,物理机挂了(比如负载高掉线,突发网络故障,硬件故障等),这些都属于节点掉线,一般默认10分30s后(主要受两个参数控制)namenode会检测到该节点通信异常掉线。然后namenode根据该节点的ip,查出该节点所有的blockid,以及对应副本所在机器,通过心跳机制安排数据复制,这时候数据的复制,数据源不在是掉线节点,而是多个副本之一所在的节点,同样这时候副本复制也遵循机架感知,副本搁置策略。
尖叫提示:节点掉线和退役两者的区别不仅是数据的复制方式不同,还有就是namenode对Under-Replicated Blocks 的数据复制策略也是不一样的(数据块block复制的等级分成5种);极端的例子比如单副本节点退役数据不会丢失,单副本节点掉线则会数据真的丢失;
1.2 如何处理节点掉线出现的各种风暴
几十T, 甚至上百T, 上百万block的节点掉线,会出现大量的RPC风暴,在我们存在大量小文件的集群对namenode是很大的挑战,不仅影响生产性能,也会存在很大的隐患,尤其是对于带宽有限制瓶颈的集群。一般来说namenode检测datanode是否掉线的值是10*3s(心跳时间)+2*5min(namenode检测时间,参数是:dfs.namenode.heartbeat.recheck-interval)=10分30s。如果在10min30s内的时间内带宽持续打满,RPC请求延迟,datanode和namenode节点通信不畅,很容易造成其他节点的持续掉线,形成恶性循环,这种情况应该如何避免?
1.2.1 Datanode的block复制
NameNode 维护一个复制优先级队列,对于副本不足的文件 block 按优先级排序,仅剩下一个副本的文件 block 享有最高的复制优先级。所以从这里看集群两副本的话,只要有一个block出现异常,就只剩一个副本,就是最高优先级的块复制,会风暴模式复制,控制不好很容易影响集群性能,甚至搞挂集群。所以一般不建议集群副本因子是2。
如下block待复制的5个优先级队列:其实就在UnderReplicatedBlocks的私有方法getPriority张中,长这样:
/**HDFSversion-3.1.1.3.1, 保持低冗余块的优先队列*/
class LowRedundancyBlocks implements Iterable<BlockInfo> {
/** The total number of queues : {@value} */
static final int LEVEL = 5;
/** The queue with the highest priority: {@value} */
static final int QUEUE_HIGHEST_PRIORITY = 0;
/** The queue for blocks that are way below their expected value : {@value} */
static final int QUEUE_VERY_LOW_REDUNDANCY = 1;
/**
* The queue for "normally" without sufficient redundancy blocks : {@value}.
*/
static final int QUEUE_LOW_REDUNDANCY = 2;
/** The queue for blocks that have the right number of replicas,
* but which the block manager felt were badly distributed: {@value}
*/
static final int QUEUE_REPLICAS_BADLY_DISTRIBUTED = 3;
/** The queue for corrupt blocks: {@value} */
static final int QUEUE_WITH_CORRUPT_BLOCKS = 4;
/** the queues themselves */
private final List<LightWeightLinkedSet<BlockInfo>> priorityQueues
= new ArrayList<>(LEVEL);
}
L1(最高):有数据丢失风险的块,如:1.只有一个副本的块(尤其对于2副本的块,下线一台节点)或者这些块有0个active副本;2,单副本在正在退役的节点拥有的块。
L2: block副本实际值远低于配置的值(比如3副本,缺失2个),即副本数不到期望值1/3时的块,这些block会被第二优先级复制。比如4副本的block,有3个丢失或者坏了,它就会比4副本block丢失2个的优先复制。
L3:副本不足没有优先级L2高的那些副本,优先复制。第三优先级。
L4: block满足要求的最小副本数。副本度需求度比L2-L3都低。
L5: 已损坏的块,并且当前有可用的非损坏副本
1.2.2 控制节点掉线RPC风暴的参数
三个参数都是hdfs-site.xml中参数,具体可以参考apache hadoop官网,其实块的复制速度有两个方面决定,一是namenode分发任务的速度,二则是datanode之间进行复制的速度。前者可以理解成入口,后者可以当成出口。
1.入口参数:从namenode层面控制任务分发,这个参数修改必须重启namenode,不需要重启datanode.
dfs.namenode.replication.work.multiplier.per.iteration
这个参数apache hadoop默认值2,cdh集群默认值10
这个参数决定了当NN与DN进行心跳(3s)发送任务列表时,告诉每个DN可以进行复制的block数量。比如集群有5个节点,这个值设置为5,那么一次心跳namnode可以发送datanode复制的数据块数量是5*5=25块。假如一个节点掉线/退役有365588块block需要复制,则namenode需要多长时间可以将待复制块的任务分发完给datanode呢。
Ambari -web namenode 参数设置如下:
极限计算的结果:
任务分发时间=待复制block总数/(集群活跃dn*参数值)*心跳时间
time=365585/(5*5)=14623 次心跳*3s/每次心跳=43870s = 大约 13 hour
所以节点越多,会分发任务越快,分发速度跟节点数和这个参数都成正比
2.出口参数:相比上面从Namenode任务分发控制,下面两个使用datanode层面控制,这两个参数也需要重启namenode
dfs.namenode.replication.max-streams
apache hadoop默认值是2,cdh集群默认20。
这个参数含义是控制datanode节点进行数据复制的最大线程数,从上面我们知道block的复制优先级分成5种。这个参数控制不包含最高优先级的块复制。即除最高优先级的复制流限制
dfs.namenode.replication.max-streams-hard-limit
这个值apache hadoop默认值2,cdh集群默认值40
这个参数含义是控制datanode所有优先级块复制的流个数,包含最高优先级;一般上面和上面两个参数互相的配合使用。
尖叫总结:前者参数控制datanode接受任务的频率,后者这两个参数进一步限制 DataNode 一次完成的最大并行线程网络传输量。具体上面参数的值设定的多少,取决于集群的规模和集群的配置,不能同一而论。一般来说从入口控制比较简单容易些。比如规模500台集群,dfs.namenode.replication.work.multiplier.per.iteration=10,5台DataNode,那么集群一次心跳分发50个block的量,假如集群文件存储全部打散在5台节点,每个节点同时复制10个block(实际会因为副本搁置策略,机架感知等并不会所有的节点都参与数据复制),每个block大小128Mb,则每个节点的网络负载是128*10/3=546Mb/s,那这时候你就要看下结合实际会不会有带宽瓶颈,这么大的网络IO会不会影响正常任务的计算,如果有的话,这个值就要调小点。
二、如何快速节点下线
如何让节点快速下线的本质其实就是提高副本的复制速度。主要还是上面三个参数控制.第一是控制namenode任务分发,其次控制datanode复制速率,前提是不影响正常生产任务的进行。集群规模越小,下线的越慢,比如因为分发的总数会慢很多。
如下是Datanode节点:
Ambari-web 参数设置:
dfs.namenode.replication.work.multiplier.per.iteration=5
dfs.namenode.replication.max-streams=10
dfs.namenode.replication.max-streams-hard-limit=20
极限计算的结果:
任务分发时间=待复制block总数/(集群活跃dn*参数值)*心跳时间
time=365585/(5*5)=14623 次心跳*3s/每次心跳=43870s = 大约 13 hour
由于集群对于小文件的处理不及时导致block 的 数量很大,加上 集群节点只有5台 所以退役一台 Datanode ,需要完成 block 复制的时间 就会很长,但是在可接受范围内。如果是节点相对比较多的节点 ,如上的参数我们继续调整。
在 active namenode 日志我们可以看到每次要复制的block 数为 50 block,需要 完成复制的 bolck 总数为 344341 等信息。
/var/log/hadoop/hdfs/hadoop-hdfs-namenode-namenode.log
2022-12-15 11:41:15,551 INFO BlockStateChange (UnderReplicatedBlocks.java:chooseUnderReplicatedBlocks(395)) - chooseUnderReplicatedBlocks selected 50 blocks at priority level 2; Total=50 Reset bookmarks? false
2022-12-15 11:41:15,552 INFO BlockStateChange (BlockManager.java:computeReplicationWorkForBlocks(1653)) - BLOCK* neededReplications = 344341, pendingReplications = 67.
2022-12-15 11:41:15,552 INFO blockmanagement.BlockManager (BlockManager.java:computeReplicationWorkForBlocks(1660)) - Blocks chosen but could not be replicated = 10; of which 0 have no target, 10 have no source, 0 are UC, 0 are abandoned, 0 already have enough replicas.
2022-12-15 11:41:15,552 INFO blockmanagement.BlockManager (BlockManager.java:rescanPostponedMisreplicatedBlocks(2121)) - Rescan of postponedMisreplicatedBlocks completed in 0 msecs. 18 blocks are left. 0 blocks were removed.
参考博客:如何提高节点下线速度或避免因节点掉线产生网络风暴?_涤生大数据的博客-CSDN博客_dfs.namenode.replication.work.multiplier.per.itera