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 官网降级文档中有介绍,概括起来大抵步骤如下:
- JournalNode降级,应用新版本顺次重启 JournalNode。
- NameNode降级筹备,生成 rollback fsimage文件。
- 应用新版本Hadoop重启 Standby NameNode,重启 ZKFC。
- NameNode HA主从切换,使降级后的 NameNode 变成 Active 节点。
- 应用新版本 Hadoop 重启另一个 NameNode,重启 ZKFC。
- 降级 DataNode,应用新版本 Hadoop 滚动重启所有 DataNode 节点。
- 执行 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降级过程:
- rename以后current目录,到previous.tmp。
- 新建current目录,并且建设hardlink从previous.tmp到新current目录。
- 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组件降级打下了根底。
在此基础上,咱们能够持续做十分有意义的工作,继续在稳定性、性能、老本等多个方面深刻摸索,应用技术为公司发明可见的价值。
参考资料
- https://issues.apache.org/jira/browse/HDFS-13596
- https://issues.apache.org/jira/browse/HDFS-14396
- https://issues.apache.org/jira/browse/HDFS-14831
- https://issues.apache.org/jira/browse/HDFS-14942
- https://issues.apache.org/jira/browse/HDFS-9788
- https://issues.apache.org/jira/browse/HDFS-3107
- https://issues.apache.org/jira/browse/HDFS-8791
- https://issues.apache.org/jira/browse/HDFS-14313
- https://issues.apache.org/jira/browse/HDFS-13671