HDFS 升级模式(Upgrade Mode)完整分析

HDFS 升级模式(Upgrade Mode)完整分析

💡 原文中文,约36300字,阅读约需87分钟。
📝

内容提要

本文深入分析HDFS升级机制,涵盖标准升级与滚动升级两种方式。核心是存储目录状态机(StorageState)实现崩溃安全,通过临时目录和原子重命名确保升级可恢复。滚动升级通过锁定布局版本保持旧格式兼容,限制新功能使用,并利用硬链接优化数据迁移。文章详细阐述了NameNode和DataNode的升级、回滚、定稿完整流程及权限控制。

🔎

延伸解读

崩溃安全设计:临时目录与原子重命名

HDFS升级的崩溃安全依赖于存储目录状态机(StorageState)和临时目录机制。升级过程中,数据先被原子重命名到previous.tmp,再创建新的current目录,最后将previous.tmp重命名为previous。任何步骤中断,重启时analyzeStorage()都能检测状态并自动恢复。这种设计确保了升级过程的可恢复性,避免了数据丢失。

硬链接优化:减少数据复制

升级时,NameNode通过硬链接将edits_*文件从previous.tmp链接到新的current目录,DataNode则对块文件使用硬链接。这样既保证了回滚时编辑日志的完整性,又避免了复制大量数据,显著提升了升级效率。硬链接使得新旧目录共享同一inode,升级过程中新写入的事务对两个路径都可见。

滚动升级的布局版本锁定与功能限制

滚动升级期间,NameNode通过getEffectiveLayoutVersion()将布局版本锁定为旧版本,确保新旧节点兼容。同时,requireEffectiveLayoutVersionForFeature()会阻止使用需要新布局版本的功能,如Truncate、Append New Block等。编辑日志和FSImage的序列化也会根据锁定的版本跳过新功能字段,保证降级时旧版本能正确读取。

回滚与定稿的不可逆性

回滚操作通过将current移为removed.tmp,再将previous恢复为current,最后删除removed.tmp,确保事务性。定稿则彻底删除previous目录,之后无法再回滚。回滚前会检查previous目录是否存在以及布局版本是否匹配,不匹配时抛出异常。这些操作都要求超级用户权限,且受dfs.permissions.enabled控制。

Q&A

HDFS升级模式有哪两种?它们的主要区别是什么?

HDFS支持标准升级和滚动升级两种方式。标准升级需要停止整个集群,有停机窗口,HA支持有限,通过previous/目录完整备份;滚动升级零停机,原生支持HA,通过fsimage_rollback*回滚镜像和标记文件实现备份。

HDFS升级过程中如何保证崩溃安全?

HDFS通过存储目录状态机(StorageState)和临时目录(如previous.tmp、removed.tmp)实现崩溃安全。升级时先将current目录原子重命名为previous.tmp,再创建新的current目录,写入新数据后,将previous.tmp重命名为previous。任何步骤崩溃后,重启时analyzeStorage()会自动检测状态并调用doRecover()恢复。

HDFS标准升级后如何回滚?

标准升级后,如果previous/目录存在且布局版本匹配,可以使用`hdfs namenode -rollback`命令回滚。回滚过程先将current目录重命名为removed.tmp,再将previous目录重命名为current,最后删除removed.tmp。回滚前会检查previous/是否存在以及布局版本是否匹配。

滚动升级期间,HDFS如何保持旧版本兼容?

滚动升级期间,NameNode通过getEffectiveLayoutVersion()将有效布局版本锁定为旧版本,确保fsimage和edit log以旧格式写入。同时,通过requireEffectiveLayoutVersionForFeature()限制使用需要新布局版本的功能,如Truncate、Append New Block等。DataNode则通过标记文件(RollingUpgradeInProgress)和Trash机制管理块删除,确保数据可恢复。

HDFS升级定稿(finalize)后还能回滚吗?

不能。定稿操作会删除previous/目录,彻底移除旧版本备份,之后无法再回滚。定稿通过`hdfs dfsadmin -finalizeUpgrade`命令执行,需要超级用户权限。

HDFS升级操作需要什么权限?

大多数升级操作(如finalizeUpgrade、rollingUpgrade prepare/finalize)需要超级用户权限,即NameNode启动用户或属于supergroup的用户。但upgradeStatus查询操作无权限限制,任何用户可执行。权限受dfs.permissions.enabled控制,若禁用则所有操作不受限。

滚动升级期间,DataNode如何处理块删除?

滚动升级期间,DataNode通过心跳接收滚动升级状态。若升级未定稿,DataNode会启用Trash机制,将删除的块文件移动到trash目录而不是直接删除,并创建标记文件(RollingUpgradeInProgress)。定稿后,清理Trash并删除标记文件,同时执行doFinalize()清理previous/目录。

HDFS升级时,NameNode和DataNode的升级流程有何不同?

NameNode升级通过FSImage.recoverTransitionRead()进行,包括目录状态分析、布局版本检查、格式化未格式化目录等,然后执行doUpgrade(),其中包含两阶段:doPreUpgrade()将current迁移到previous.tmp并硬链接edits文件,doUpgrade()写VERSION并完成重命名。DataNode升级分为DataStorage层级和BlockPoolSliceStorage层级,DataStorage处理DN级存储,BlockPoolSliceStorage处理块池级存储,升级时也会使用硬链接优化块文件迁移。

🏷️

标签

➡️

继续阅读