vivo 互联网大数据团队-Lv Jia

Hadoop 3.x的第一个稳固版本在2017年底就曾经公布了,有很多重大的改良。

在HDFS方面,反对了Erasure Coding、More than 2 NameNodes、Router-Based Federation、Standby NameNode Read、FairCallQueue、Intra-datanode balancer 等新个性。这些新个性在稳定性、性能、老本等多个方面带来诸多收益,咱们打算将HDFS集群降级到HDFS 3.x 版本。

本篇文章会介绍咱们是如何将CDH 5.14.4 HDFS 2.6.0 滚动降级到HDP-3.1.4.0-315 HDFS 3.1.1版本,是业界为数不多的从CDH集群滚动降级到HDP集群的案例。在降级中遇到哪些问题?这些问题是如何解决掉的?本篇文章具备十分高的参考借鉴价值。

一、 背景

vivo离线数仓Hadoop集群基于CDH 5.14.4版本构建,CDH 5.14.4 Hadoop版本:2.6.0+CDH 5.14.4+2785,是Cloudera公司基于Apache Hadoop 2.6.0版本打入了一些优化patch后的Hadoop发行版。

近几年随着vivo业务倒退,数据爆炸式增长,离线数仓HDFS集群从一个扩大到十个,规模靠近万台。随着 HDFS 集群规模的增长,以后版本的HDFS的一些痛点问题也裸露进去:

  • 在以后低版本的HDFS,线上环境NameNode经常出现RPC性能问题,用户Hive/Spark离线工作也会因为NameNode RPC性能变慢导致工作提早。
  • 一些RPC性能问题在HDFS 3.x版本均已修复,以后只能通过打入HDFS高版本patch的形式解决线上NameNode RPC性能问题。
  • 频繁的patch合并减少了HDFS代码保护的复杂度,每一个patch的上线都须要重启NameNode或者DataNode,减少了HDFS集群的运维老本。
  • 线上HDFS集群应用viewfs对外提供服务,公司外部业务线泛滥,很多业务部门申请了独立的HDFS客户端拜访离线数仓集群。当批改线上HDFS配置后,更新HDFS客户端配置是一件十分耗时且麻烦的事件。
  • HDFS 2.x不反对EC,冷数据无奈应用EC来升高存储老本。

Hadoop 3.x的第一个稳固版本在2017年底就曾经公布了,有了很多重大的改良。在HDFS方面,反对了Erasure Coding、More than 2 NameNodes、Router-Based Federation、Standby NameNode Read、FairCallQueue、Intra-datanode balancer 等新个性。HDFS 3.x新个性在稳定性、性能、老本等多个方面带来诸多收益

  • HDFS Standby NameNode Read、FairCallQueue新个性以及HDFS 3.x NameNode RPC优化patch能极大晋升咱们以后版本HDFS集群稳定性与RPC性能。
  • HDFS RBF代替viewfs,简化HDFS客户端配置更新流程,解决线上更新泛滥HDFS客户端配置的痛点问题。
  • HDFS EC利用冷数据存储,升高存储老本。

基于以上痛点问题与收益,咱们决定将离线数仓HDFS集群降级到 HDFS 3.x版本。

二、 HDFS 降级版本抉择

因为咱们Hadoop集群基于CDH 5.14.4版本构建,咱们首先思考降级到CDH高版本。CDH 7提供HDFS 3.x发行版,遗憾是CDH 7没有免费版,咱们只能抉择降级到Apache版本或者Hortonworks公司提供的HDP发行版。

因为Apache Hadoop没有提供管理工具,对于万台规模的HDFS集群,治理配置、散发配置极其不不便。因而,咱们抉择了Hortonworks HDP发行版,HDFS管理工具抉择Ambari。

Hortonworks提供的最新的稳固的收费的Hadoop发行版为HDP-3.1.4.0-315版本。Hadoop版本为Apache Hadoop 3.1.1版本。

三、HDFS 降级计划制订

3.1 降级计划

HDFS官网提供两种降级计划:Express 和 RollingUpgrade

  • Express 降级过程是进行现有HDFS服务,而后应用新版本HDFS启动服务,会影响线上业务失常运行。
  • RollingUpgrade 降级过程是滚动降级,不停服务,对用户无感知。

鉴于HDFS停服对业务影响较大,咱们最终抉择 RollingUpgrade计划。

3.2 降级计划

RollingUpgrade 计划中, 有两种回退形式:Rollback 和 RollingDowngrade 

  • Rollback 会把HDFS版本连同数据状态回退到降级前的那一刻 ,会造成数据失落。
  • RollingDowngrade 只回退HDFS版本,数据不受影响。

咱们线上 HDFS 集群是不能容忍数据失落的,咱们最终抉择 RollingDowngrade 的回退计划。

3.3  HDFS 客户端降级计划

线上 Spark、Hive、Flink 、OLAP等计算组件重度依赖HDFS Client,局部计算组件版本过低,须要降级到高版本能力反对HDFS 3.x,降级HDFS Client有较高风险。

咱们在测试环境通过多轮测试,验证了HDFS 3.x兼容HDFS 2.x client读写。

因而,咱们本次HDFS降级只降级NameNode、JournalNode、DataNode组件,HDFS 2.x Client等YARN降级后再降级。

3.4 HDFS 滚动降级步骤

RollingUpgrade 降级的操作流程在 Hadoop 官网降级文档中有介绍,概括起来大抵步骤如下:

  1. JournalNode降级,应用新版本顺次重启 JournalNode。
  2. NameNode降级筹备,生成 rollback fsimage文件。
  3. 应用新版本Hadoop重启 Standby NameNode,重启 ZKFC。
  4. NameNode HA主从切换,使降级后的 NameNode 变成 Active 节点。
  5. 应用新版本 Hadoop 重启另一个 NameNode,重启 ZKFC。
  6. 降级 DataNode,应用新版本 Hadoop 滚动重启所有 DataNode 节点。
  7. 执行 Finalize,确认HDFS集群降级到新版本。

四、管理工具如何共存

HDFS 2.x集群,HDFS、YARN、Hive、HBase等组件,应用CM工具治理。因为只降级HDFS,HDFS 3.x应用Ambari治理,其它组件如YARN、Hive依然应用CM治理。HDFS 2.x client不降级,持续应用CM治理。Zookeeper应用原CM部署的ZK。

具体实现:CM Server节点部署Amari Server,CM Agent节点部署Ambari Agent。

如上图所示,应用Ambari工具在master/slave节点部署HDFS 3.x NameNode/DataNode组件,因为端口抵触,Ambari部署的HDFS 3.x会启动失败,不会对线上CM部署的HDFS 2.x集群产生影响。

HDFS降级开始后,master节点进行CM JN/ZKFC/NN,启动Ambari JN/ZKFC/NN,slave节点进行CM DN,启动Ambari DN。HDFS降级的同时实现管理工具从CM切换到Ambari。

五、HDFS 滚动降级降级过程中遇到的问题

5.1 HDFS 社区已修复的不兼容问题

HDFS社区已修复滚动降级、降级过程中要害不兼容的问题。相干issue号为:HDFS-13596、 HDFS-14396、 HDFS-14831。

【HDFS-13596】: 修复Active NamNode降级后将EC相干的数据结构写入EditLog 文件,导致Standby NameNode读取EditLog 异样间接Shutdown的问题。

【HDFS-14396】:修复NameNode降级到HDFS 3.x版本后,将EC相干的数据结构写入Fsimage文件,导致NameNode降级到HDFS 2.x版本辨认Fsimage文件异样的问题。

【HDFS-14831】:修复NameNode降级后对 StringTable 的批改导致HDFS降级后 Fsimage 不兼容问题。

咱们降级的HDP HDFS版本引入了上述三个issue相干的代码。除此之外,咱们在降级过程中还遇到了其它的不兼容问题:

5.2 JournalNode 降级呈现 Unknown protocol

JournalNode降级过程中,呈现的问题:

Unknown protocol: org.apache.hadoop.hdfs.qjournal.protocol.InterQJournalProtocol
org.apache.hadoop.ipc.RemoteException(org.apache.hadoop.ipc.RpcNoSuchProtocolException): Unknown protocol: org.apache.hadoop.hdfs.qjournal.protocol.InterQJournalProtocol        at org.apache.hadoop.ipc.ProtobufRpcEngine$Server$ProtoBufRpcInvoker.getProtocolImpl(ProtobufRpcEngine.java:557)        at org.apache.hadoop.ipc.ProtobufRpcEngine$Server$ProtoBufRpcInvoker.call(ProtobufRpcEngine.java:596)        at org.apache.hadoop.ipc.RPC$Server.call(RPC.java:1073)        at org.apache.hadoop.ipc.Server$Handler$1.run(Server.java:2281)        at org.apache.hadoop.ipc.Server$Handler$1.run(Server.java:2277)        at java.security.AccessController.doPrivileged(Native Method)        at javax.security.auth.Subject.doAs(Subject.java:415)        at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1924)        at org.apache.hadoop.ipc.Server$Handler.run(Server.java:2275)        at org.apache.hadoop.ipc.Client.getRpcResponse(Client.java:1498)        at org.apache.hadoop.ipc.Client.call(Client.java:1444)        at org.apache.hadoop.ipc.Client.call(Client.java:1354)        at org.apache.hadoop.ipc.ProtobufRpcEngine$Invoker.invoke(ProtobufRpcEngine.java:228)        at org.apache.hadoop.ipc.ProtobufRpcEngine$Invoker.invoke(ProtobufRpcEngine.java:116)        at com.sun.proxy.$Proxy14.getEditLogManifestFromJournal(Unknown Source)        at org.apache.hadoop.hdfs.qjournal.protocolPB.InterQJournalProtocolTranslatorPB.getEditLogManifestFromJournal(InterQJournalProtocolTranslatorPB.java:75)        at org.apache.hadoop.hdfs.qjournal.server.JournalNodeSyncer.syncWithJournalAtIndex(JournalNodeSyncer.java:250)        at org.apache.hadoop.hdfs.qjournal.server.JournalNodeSyncer.syncJournals(JournalNodeSyncer.java:226)        at org.apache.hadoop.hdfs.qjournal.server.JournalNodeSyncer.lambda$startSyncJournalsDaemon$0(JournalNodeSyncer.java:186)        at java.lang.Thread.run(Thread.java:748)

报错起因:HDFS 3.x新增了InterQJournalProtocol,新减少的InterQJournalProtocol用于JournalNode之间同步旧的edits数据。

HDFS-14942 对此问题进行了优化,日志级别从ERROR改成DEBUG。此问题不影响降级,当三个HDFS 2.x JN全副降级为HDFS 3.x JN时,JN之间能失常同步数据。

5.3 NameNode降级DatanodeProtocol.proto不兼容

NameNode降级后,DatanodeProtocol.proto不兼容,导致Datanode BlockReport 无奈进行。

(1)HDFS 2.6.0 版本

DatanodeProtocol.proto
message HeartbeatResponseProto {  repeated DatanodeCommandProto cmds = 1; // Returned commands can be null  required NNHAStatusHeartbeatProto haStatus = 2;  optional RollingUpgradeStatusProto rollingUpgradeStatus = 3;  optional uint64 fullBlockReportLeaseId = 4 [ default = 0 ];  optional RollingUpgradeStatusProto rollingUpgradeStatusV2 = 5;}

(2)HDFS 3.1.1版本

DatanodeProtocol.proto
message HeartbeatResponseProto {  repeated DatanodeCommandProto cmds = 1; // Returned commands can be null  required NNHAStatusHeartbeatProto haStatus = 2;  optional RollingUpgradeStatusProto rollingUpgradeStatus = 3;  optional RollingUpgradeStatusProto rollingUpgradeStatusV2 = 4;  optional uint64 fullBlockReportLeaseId = 5 [ default = 0 ];}

咱们能够看到两个版本 HeartbeatResponseProto 的第4、5个参数地位调换了

这个问题的起因在于,Hadoop 3.1.1 版本commit了 HDFS-9788,用来解决HDFS降级时兼容低版本问题,而 HDFS 2.6.0 版本没有commit ,导致了DatanodeProtocol.proto不兼容。

HDFS降级过程中,不须要兼容低版本HDFS,只须要兼容低版本HDFS client。

因而,HDFS 3.x不须要 HDFS-9788 兼容低版本的性能,咱们在Hadoop 3.1.1 版本回退了 HDFS-9788 的批改来放弃和HDFS 2.6.0 版本的DatanodeProtocol.proto兼容。

5.4  NameNode降级layoutVersion不兼容

NameNode降级后,NameNode layoutVersion扭转,导致EditLog不兼容,HDFS 3.x降级到HDFS 2.x NameNode 无奈启动。

2021-04-12 20:15:39,571 ERROR org.apache.hadoop.hdfs.server.namenode.EditLogInputStream: caught exception initializing XXX:8480/getJournalid=test-53-39&segmentTxId=371054&storageInfo=-60%3A1589021536%3A0%3Acluster7org.apache.hadoop.hdfs.server.namenode.EditLogFileInputStream$LogHeaderCorruptException: Unexpected version of the file system log file: -64. Current version = -60.        at org.apache.hadoop.hdfs.server.namenode.EditLogFileInputStream.readLogVersion(EditLogFileInputStream.java:397)        at org.apache.hadoop.hdfs.server.namenode.EditLogFileInputStream.init(EditLogFileInputStream.java:146)        at org.apache.hadoop.hdfs.server.namenode.EditLogFileInputStream.nextopImpl(EditLogFileInputStream.java:192)        at org.apache.hadoop.hdfs.server.namenode.EditLogFileInputStream.nextop(EditLogFileInputStream.java:250)        at org.apache.hadoop.hdfs.server.namenode.EditLogInputStream.read0p(EditLogInputStream.java:85)        at org.apache.hadoop.hdfs.server.namenode.EditLogInputStream.skipUntil(EditLogInputStream.java:151)        at org.apache.hadoop.hdfs.server.namenode.RedundantEditLogInputStream.next0p(RedundantEditLogInputStream.java:178)        at org.apache.hadoop.hdfs.server.namenode.EditLogInputStream.readop(EditLogInputStream.java:85)        at org.apache.hadoop.hdfs.server.namenode.EditLogInputStream.skipUntil(EditLogInputStream.java:151)        at org.apache.hadoop.hdfs.server.namenode.RedundantEditLogInputStream.next0p(RedundantEditLogInputStream.java:178)        at org.apache.hadoop.hdfs.server.namenode.EditLogInputStream.read0p(EditLogInputStream.java:85)        at org.apache.hadoop.hdfs.server.namenode.FSEditLogLoader.LoadEditRecords(FSEditLogLoader.java:188)        at org.apache.hadoop.hdfs.server.namenode.FSEditLogLoader.LoadFSEdits(FSEditLogLoader.java:141)        at org.apache.hadoop.hdfs.server.namenode.FSImage.loadEdits(FSImage.java:903)        at org.apache.hadoop.hdfs.server.namenode.FSImage.LoadFSImage(FSImage.java:756)        at org.apache.hadoop.hdfs.server.namenode.FSImage.recoverTransitionRead(FSImage.java:324)        at org.apache.hadoop.hdfs.server.namenode.FSNamesystem.LoadFSImage(FSNamesystem.java:1150)        at org.apache.hadoop.hdfs.server.namenode.FSNamesystem.LoadFromDisk(FSNamesystem.java:797)        at org.apache.hadoop.hdfs.server.namenode.NameNode.LoadNamesystem (NameNode.java:614)        at org.apache.hadoop.hdfs.server.namenode.NameNode.initialize(NameNode.java:676)        at org.apache.hadoop.hdfs.server.namenode.NameNode.<init>(NameNode.java:844)        at org.apache.hadoop.hdfs.server.namenode.NameNode.<init>(NameNode.java:823)        at org.apache.hadoop.hdfs.server.namenode.NameNode.createNameNode (NameNode.java:1547)        at org.apache.hadoop.hdfs.server.namenode.NameNode.main(NameNode.java:1615)

HDFS 2.6.0降级到HDFS 3.1.1,NameNode layoutVersion值 -60 变更成 -64。要解决这个问题,首先搞清楚NameNode layoutVersion什么状况下会变更?

HDFS版本升级引入新个性,NameNode layoutVersion追随新个性变更。Hadoop官网降级文档指出,HDFS滚动降级过程中要禁用新个性,保障降级过程中layoutVersion不变,降级后的HDFS 3.x版本能力回退到HDFS 2.x版本。

接下来,找出HDFS 2.6.0降级到HDFS 3.1.1引入了哪一个新个性导致namenode layoutVersion变更?查看 HDFS-5223、HDFS-8432、HDFS-3107相干issue,HDFS 2.7.0版本引入了truncate性能,NameNode layoutVersion变成 -61。查看HDFS 3.x版本NameNodeLayoutVersion代码:

NameNodeLayoutVersion
public enum Feature implements LayoutFeature {  ROLLING_UPGRADE(-55, -53, -55, "Support rolling upgrade", false),  EDITLOG_LENGTH(-56, -56, "Add length field to every edit log op"),  XATTRS(-57, -57, "Extended attributes"),  CREATE_OVERWRITE(-58, -58, "Use single editlog record for " +    "creating file with overwrite"),  XATTRS_NAMESPACE_EXT(-59, -59, "Increase number of xattr namespaces"),  BLOCK_STORAGE_POLICY(-60, -60, "Block Storage policy"),  TRUNCATE(-61, -61, "Truncate"),  APPEND_NEW_BLOCK(-62, -61, "Support appending to new block"),  QUOTA_BY_STORAGE_TYPE(-63, -61, "Support quota for specific storage types"),  ERASURE_CODING(-64, -61, "Support erasure coding");

TRUNCATE、APPEND\_NEW\_BLOCK、QUOTA\_BY\_STORAGE\_TYPE、ERASURE\_CODING 四个Feature设置了minCompatLV为-61。

查看最终NameNode layoutVersion取值逻辑:

FSNamesystem
static int getEffectiveLayoutVersion(boolean isRollingUpgrade, int storageLV,    int minCompatLV, int currentLV) {  if (isRollingUpgrade) {    if (storageLV <= minCompatLV) {      // The prior layout version satisfies the minimum compatible layout      // version of the current software.  Keep reporting the prior layout      // as the effective one.  Downgrade is possible.      return storageLV;    }  }  // The current software cannot satisfy the layout version of the prior  // software.  Proceed with using the current layout version.  return currentLV;}

getEffectiveLayoutVersion获取最终失效的layoutVersion,storageLV是以后HDFS 2.6.0版本layoutVersion -60,minCompatLV是 -61,currentLV是降级后的HDFS 3.1.1版本layoutVersion -64。

从代码判断逻辑能够看出,HDFS 2.6.0版本layoutVersion -60 小于等于minCompatLV是 -61不成立,因而,降级到HDFS 3.1.1版本后,namenode layoutVersion的取值为currentLV -64。

从上述代码剖析能够看出,HDFS 2.7.0版本引入了truncate性能后,HDFS社区只反对HDFS 3.x 降级到HDFS 2.7版本的NameNode layoutVersion是兼容的。

咱们对HDFS truncate性能进行评估,联合业务场景剖析,咱们vivo外部离线剖析临时没有应用HDFS truncate性能的场景。基于此,咱们批改了HDFS 3.1.1版本的minCompatLV为 -60,用来反对HDFS 2.6.0降级到HDFS 3.1.1版本后可能降级到HDFS 2.6.0。

minCompatLV批改为-60:

NameNodeLayoutVersion
public enum Feature implements LayoutFeature {  ROLLING_UPGRADE(-55, -53, -55, "Support rolling upgrade", false),  EDITLOG_LENGTH(-56, -56, "Add length field to every edit log op"),  XATTRS(-57, -57, "Extended attributes"),  CREATE_OVERWRITE(-58, -58, "Use single editlog record for " +    "creating file with overwrite"),  XATTRS_NAMESPACE_EXT(-59, -59, "Increase number of xattr namespaces"),  BLOCK_STORAGE_POLICY(-60, -60, "Block Storage policy"),  TRUNCATE(-61, -60, "Truncate"),  APPEND_NEW_BLOCK(-62, -60, "Support appending to new block"),  QUOTA_BY_STORAGE_TYPE(-63, -60, "Support quota for specific storage types"),  ERASURE_CODING(-64, -60, "Support erasure coding");

5.5 DataNode降级layoutVersion不兼容

DataNode降级后,DataNode layoutVersion不兼容,HDFS 3.x DataNode降级到HDFS 2.x DataNode无奈启动。

2021-04-19 10:41:01,144 WARN org.apache.hadoop.hdfs.server.common.Storage: Failed to add storage directory [DISK]file:/data/dfs/dn/org.apache.hadoop.hdfs.server.common.IncorrectVersionException: Unexpected version of storage directory /data/dfs/dn. Reported: -57. Expecting = -56.        at org.apache.hadoop.hdfs.server.common.StorageInfo.setLayoutVersion(StorageInfo.java:178)        at org.apache.hadoop.hdfs.server.datanode.DataStorage.setFieldsFromProperties(DataStorage.java:665)        at org.apache.hadoop.hdfs.server.datanode.DataStorage.setFieldsFromProperties(DataStorage.java:657)        at org.apache.hadoop.hdfs.server.common.StorageInfo.readProperties(StorageInfo.java:232)        at org.apache.hadoop.hdfs.server.datanode.DataStorage.doTransition(DataStorage.java:759)        at org.apache.hadoop.hdfs.server.datanode.DataStorage.LoadStorageDirectory(DataStorage.java:302)        at org.apache.hadoop.hdfs.server.datanode.DataStorage.LoadDataStorage(DataStorage.java:418)        at org.apache.hadoop.hdfs.server.datanode.DataStorage.addStorageLocations(DataStorage.java:397)        at org.apache.hadoop.hdfs.server.datanode.DataStorage.recoverTransitionRead(DataStorage.java:575)        at org.apache.hadoop.hdfs.server.datanode.DataNode.initStorage(DataNode.java:1560)        at org.apache.hadoop.hdfs.server.datanode.DataNode.initBLockPool(DataNode.java:1520)        at org.apache.hadoop.hdfs.server.datanode.BPOfferService.verifyAndSetNamespaceInfo(BPOfferService.java:341)        at org.apache.hadoop.hdfs.server.datanode.BPServiceActor.connectToNNAndHandshake(BPServiceActor.java:219)        at org.apache.hadoop.hdfs.server.datanode.BPServiceActor.run(BPServiceActor.java:673)        at java.lang.Thread.run(Thread.java:748)

HDFS 2.6.0 DataNode layoutVersion是 -56,HDFS 3.1.1 DataNode layoutVersion是 -57。

DataNode layoutVersion扭转的起因:Hadoop社区自 HDFS-2.8.0  commit HDFS-8791 后,对DataNode的Layout进行了降级,DataNode Block Pool数据块目录存储构造从256 x 256个目录变成了32 x 32个目录。目标是通过缩小DataNode目录层级来优化Du操作引发的性能问题。

DataNode Layout降级过程:

  1. rename以后current目录,到previous.tmp。
  2. 新建current目录,并且建设hardlink从previous.tmp到新current目录。
  3. rename目录previous.tmp为previous目录。

Layout降级流程图:

DN Layout降级过程中存储目录构造:

hardlink的link关联模式图:

查看DataNodeLayoutVersion代码,定义了32 x 32个目录构造的layoutVersion是-57。阐明DataNode Layout降级须要扭转layoutVersion。

DataNodeLayoutVersion
public enum Feature implements LayoutFeature {  FIRST_LAYOUT(-55, -53, "First datanode layout", false),  BLOCKID_BASED_LAYOUT(-56,      "The block ID of a finalized block uniquely determines its position " +      "in the directory structure"),  BLOCKID_BASED_LAYOUT_32_by_32(-57,      "Identical to the block id based layout (-56) except it uses a smaller"      + " directory structure (32x32)");

咱们在测试环境进行DataNode Layout降级发现有如下问题:DataNode创立新的current目录并建设hardlink的过程十分耗时,100万block数的DataNode从Layout降级开始到对外提供读写服务须要5分钟。这对于咱们靠近万台DataNode的HDFS集群是不能承受的,难以在预约的降级工夫窗口内实现DataNode 的降级。

因而,咱们在HDFS 3.1.1版本回退了 HDFS-8791,DataNode不进行Layout降级。测试发现100~200万block数的DataNode降级只须要90~180秒,比照Layout降级工夫大幅缩短。

回退了 HDFS-8791,DataNode Du带来的性能问题怎么解决呢?

咱们梳理了HDFS 3.3.0版本的patch,发现了HDFS-14313 从内存中计算DataNode应用空间,不再应用Du操作, 完满的解决了DataNode Du性能问题。咱们在降级后的HDFS 3.1.1版本打入HDFS-14313,解决了DataNode降级后Du操作带来的io性能问题。

5.6 DataNode Trash目录解决

上图所示,DataNode降级过程中,DataNode 在删除 Block 时,是不会真的将 Block 删除的,而是先将Block 文件放到磁盘BlockPool 目录下一个 trash 目录中,为了可能应用原来的 rollback_fsimage 复原降级过程中删除的数据。咱们集群磁盘的均匀水位始终在80%,原本就很缓和,降级期间trash 中的大量Block文件会对集群稳定性造成很大威逼。

思考到咱们的计划回退形式是滚动降级而非Rollback,并不会用到trash 中的Block。所以咱们应用脚本定时对 trash 中的 Block 文件进行删除,这样能够大大减少 Datanode 上磁盘的存储压力。

5.7  其它问题

上述就是咱们HDFS降级降级过程中遇到的所有不兼容问题。除了不兼容问题,咱们还在降级的HDP HDFS 3.1.1版本引入了一些NameNode RPC 优化patch。

HDFS 2.6.0版本FoldedTreeSet红黑树数据结构导致NameNode运行一段时间后RPC性能降落,集群呈现大量StaleDataNode,导致工作读取block块失败。Hadoop 3.4.0 HDFS-13671 修复了这个问题,将FoldedTreeSet回退为原来的LightWeightResizableGSet 链表数据结构。咱们也将HDFS-13671 patch引入咱们降级的HDP HDFS 3.1.1版本。

降级后HDFS-13671的优化成果:集群StaleDataNode数量大幅缩小。

六、测试与上线

咱们在2021年3月份启动离线数仓集群HDFS降级专项,在测试环境搭建了多套HDFS集群进行了viewfs模式下多轮HDFS降级、降级演练。一直的总结与欠缺降级计划,解决降级过程中遇到的问题。

6.1 全量组件 HDFS 客户端兼容性测试

在HDFS降级中只降级了Server端,HDFS Client还是HDFS 2.6.0版本。因而,咱们要保障业务通过HDFS 2.6.0 Client能失常读写HDFS 3.1.1集群。

咱们在测试环境,搭建了线上环境相似的HDFS测试集群,联结计算组共事与业务部门,对Hive、Spark、OLAP(kylin、presto、druid)、算法平台应用HDFS 2.6.0 Client读写HDFS 3.1.1,模仿线上环境进行了全量业务的兼容性测试。确认HDFS 2.6.0 Client能失常读写HDFS 3.1.1集群,兼容性失常。

6.2 降级操作脚本化

咱们严格梳理了HDFS降级降级的命令,梳理了每一步操作的危险与注意事项。通过CM、Ambari API启停HDFS服务。将这些操作都整顿成python脚本,缩小人为操作带来的危险。

6.3 降级点检

咱们梳理了HDFS降级过程中的关键点检事项,确保HDFS降级过程中呈现问题能第一工夫发现,进行回退,降底对业务的影响。

6.4 正式降级

咱们在测试环境中进行了屡次HDFS降级降级演练,实现HDFS兼容性测试相干的工作,公司外部写了多篇WIKI 文档进行记录。

确认测试环境HDFS降级降级没问题之后,咱们开始了降级之路。

相干的具体里程碑上线过程如下:

  • 2021年3~4月,梳理HDFS 3.x版本新个性与相干patch,浏览HDFS滚动降级降级的源码,确定最终降级的HDFS 3.x版本。实现HDFS 2.x已有优化patch与HDFS 3.x高版本patch移植到降级的HDFS 3.x版本。
  • 2021年5~8月,进行HDFS降级降级演练,全量Hive、Spark、OLAP(kylin、presto、druid)兼容性测试,确定HDFS降级降级计划没有问题。
  • 2021年9月,yarn日志聚合HDFS集群(百台)降级到HDP HDFS 3.1.1,期间修复日志聚合大量ls调用导致的RPC性能问题,业务未受到影响。
  • 2021年11月,7个离线数仓HDFS集群(5000台左右)降级到HDP HDFS 3.1.1,用户无感知,业务未受到影响。
  • 2022年1月,实现离线数仓HDFS集群(10个集群规模靠近万台)降级到HDP HDFS 3.1.1,用户无感知,业务未受到影响。

降级之后,咱们对离线数仓各个集群进行了察看,目前HDFS服务运行失常。

七、总结

咱们耗时一年工夫将万台规模的离线数仓HDFS集群从CDH HDFS 2.6.0降级到了HDP HDFS 3.1.1版本,管理工具从CM胜利切换到了Ambari。

HDFS 降级过程漫长,然而收益是十分多的,HDFS降级为后续YARN、Hive/Spark、HBase组件降级打下了根底。

在此基础上,咱们能够持续做十分有意义的工作,继续在稳定性、性能、老本等多个方面深刻摸索,应用技术为公司发明可见的价值。

参考资料

  1. https://issues.apache.org/jira/browse/HDFS-13596
  2. https://issues.apache.org/jira/browse/HDFS-14396
  3. https://issues.apache.org/jira/browse/HDFS-14831
  4. https://issues.apache.org/jira/browse/HDFS-14942
  5. https://issues.apache.org/jira/browse/HDFS-9788
  6. https://issues.apache.org/jira/browse/HDFS-3107
  7. https://issues.apache.org/jira/browse/HDFS-8791
  8. https://issues.apache.org/jira/browse/HDFS-14313
  9. https://issues.apache.org/jira/browse/HDFS-13671