找回密码
 会员注册
查看: 18|回复: 0

vivo万台规模HDFS集群升级HDFS3.x实践

[复制链接]

2万

主题

0

回帖

7万

积分

超级版主

积分
72841
发表于 2024-10-4 22:25:40 | 显示全部楼层 |阅读模式
vivo 互联网大数据团队-Lv JiaHadoop 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+cdh5.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 protocolJournalNode升级过程中,出现的问题:Unknown protocolrg.apache.hadoop.hdfs.qjournal.protocol.InterQJournalProtocolorg.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.protomessage 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.protomessage 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-1220:15:39,571ERRORorg.apache.hadoop.hdfs.server.namenode.EditLogInputStream:caughtexceptioninitializingXXX: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.(NameNode.java:844) at org.apache.hadoop.hdfs.server.namenode.NameNode.(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代码:NameNodeLayoutVersionpublic 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取值逻辑:FSNamesystemstatic int getEffectiveLayoutVersion(boolean isRollingUpgrade, int storageLV, int minCompatLV, int currentLV) { if (isRollingUpgrade) { if (storageLV
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 会员注册

本版积分规则

QQ|手机版|心飞设计-版权所有:微度网络信息技术服务中心 ( 鲁ICP备17032091号-12 )|网站地图

GMT+8, 2025-1-12 04:03 , Processed in 0.516022 second(s), 25 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表