vlambda博客
学习文章列表

HDFS-16420: HDFS EC 可能会丢数据!

1概述

最近 HDFS JIRA 关于 EC 纠删码有个值得关注的 bug:在删除冗余 striped blocks 时,可能会将同一机架上其他唯一的 data block 删除,从而造成数据丢失。


目前前社区通过 HDFS-16420 在 3.2.3、3.3.2、3.4.0 这三个版本中修复了该 bug:

该 bug 是在删除冗余 striped blocks 时触发,本文以 HDFS 3.3.1 为例,先分析该 bug 产生的原因,再讨论如何修复 bug。


2原因

目前 Striped Block 和 Contiguous Block 删除冗余数据调用的方法大致相同。为方便表述,下文用 Contiguous Block 和 replica 来说明删除冗余块的细节,对于 Striped Block 而言,将 replica 替换为 internal block 即可。


删除冗余块的时序图如下:

HDFS-16420: HDFS EC 可能会丢数据!

可以看到,每次筛选待删除的冗余 replica 时,都会更新剩余待删除 replica 所在的 DatanodeStorageInfo 列表信息,这部分更新逻辑在 adjustSetsWithChosenReplica 方法中实现,如下:

public void adjustSetsWithChosenReplica(
    final Map<String, List<DatanodeStorageInfo>> rackMap,
    final List<DatanodeStorageInfo> moreThanOne,
    final List<DatanodeStorageInfo> exactlyOne,
    final DatanodeStorageInfo cur) 
{

  final String rack = getRack(cur.getDatanodeDescriptor());
  final List<DatanodeStorageInfo> storages = rackMap.get(rack);
  storages.remove(cur);
  if (storages.isEmpty()) {
    rackMap.remove(rack);
  }
  if (moreThanOne.remove(cur)) {
    if (storages.size() == 1) {
      final DatanodeStorageInfo remaining = storages.get(0);
      moreThanOne.remove(remaining);
      exactlyOne.add(remaining);
    }
  } else {
    exactlyOne.remove(cur);
  }
}

参数含义如下:

  • rackMap: 所有 replica 的 rack 到 DatanodeStorageInfo 列表的映射的哈希表

  • moreThanOne: 同一 rack 多于一个 replica 的 DatanodeStorageInfo 待删除候选列表

  • exactlyOne: 同一 rack 只有一个 replica 的 DatanodeStorageInfo 待删除候选列表

  • cur: 待删除 replica 所在的 DatanodeStorageInfo


在处理 Contiguous Block 多余的 replicas 时,其 rackMap 的DatanodeStorageInfo 列表等于如下两部分之和:

  1. moreThanOne 中 DatanodeStorageInfo 列表

  2. exactlyOne 中 DatanodeStorageInfo 列表


对于 Striped Block 而言,其一个 Block Group 有多个 internal block,这些 internal block 并不相同,而冗余的就是这些 internal block。其 rackMap 的 DatanodeStorageInfo 列表等于如下三部分之和:

  1. moreThanOne 中 DatanodeStorageInfo 列表

  2. exactlyOne 中 DatanodeStorageInfo 列表

  3. 不冗余 internal block 所在的 DatanodeStorageInfo 列表


以下图为例:


dataBlock1、dataBlock6 是待删除的冗余 internal block,则

  • moreThanOne:["dn7", "dn8", "dn10"]

  • exactlyOne: ["dn1", "dn12"]

  • rackMap: [{"/rack1": ["dn1"]}; {"/rack2": ["dn2"]}; ... {"rack9": ["dn12"]}]


回到前面的代码,在 moreThanOne 删除 DatanodeStorageInfo X 后,若 X 所在机架 R 只剩一个 DatanodeStorageInfo Y 时,则将 Y 从 moreThanOne 中删除,并添加到 exactlyOne 中。对于 Striped Block 类型而言,剩下的 Y 不一定属于 moreThanOne,其还可能是不冗余 internal block 所在的 DatanodeStorageInfo。当前实现的代码会将 Y 错误的加入到 exactlyOne 中,并在后续逻辑中删除,从而引起 internal block 丢失。


当然,在大多数情况下该 bug 并不会真的造成数据丢失,原因是当 NameNode 检查到 block 丢失时,会通过心跳向 DataNode 发送恢复 block 的指令,然后 DataNode 通过计算剩下的 data blocks 和 parity blocks 来恢复缺失的 block。

但如果短时间内同一 block group 中多块唯一的 blocks 被误删,则会导致 HDFS 无法通过剩余的 blocks 来恢复缺失的 blocks。以 RS-6-3 策略为例,若短时间内 4 块和 4 块以上 blocks 丢失,HDFS 将无法重新构建出缺失的 blocks,造成数据丢失。从 HDFS-16420 的讨论看,确实有部分用户的数据丢失。


知道了 bug 原因,那么修改该问题的思路就很简单了:若 moreThanOne 能成功删除 remaining,才将 remaining 加入到 exactlyOne 中,如 HDFS-16420 的 patch 所示:

if (moreThanOne.remove(remaining)) {
  exactlyOne.add(remaining);
}

何时检测并删除冗余块

从源码的调用来看,如下几种情况会触发检测冗余块的流程:

  1. 新添加 block 到 blocksMap

  2. 文件最终写入时,在关闭文件后,会检查该文件相关的 block 是否冗余

  3. 从 decommission 或 maintenance 状态出来的 DataNode 重新上线

  4. 检测 block 异常的 replica 数,如 fsck 命令的 -replicate 参数

  5. 设置副本数

对于 EC 而言,主要是前三种情况触发冗余块的检测。


3受影响版本

如下版本会受到该 bug 影响:

  • 除 hadoop 3.2.3、hadoop 3.3.2 和 hadoop 3.4.0 以下的 hadoop 3.x.x 系列版本

  • cdh 6.0.x、6.1.x、6.2.x、6.3.x

  • HDP 3.0.x、HDP 3.1.x

即便使用上述版本的大数据平台,若目录未配置 EC 策略,也不会受到影响。

命令

// 查看指定目录下哪些文件使用了 EC:
$ hdfs fsck /path -files | grep " erasure-coded:"
// 查看指定目录的策略:
$ hdfs ec -getPolicy -path /path
//取消指定目录的 EC 策略:
$ hdfs ec -unsetPolicy -path /path


4修复方案

  • 若使用商业大数据平台,可咨询供应商如何修复;

  • 若使用开源 Hadoop 方案,通过 git cherry-pick 87ea3b1418a34ed3 修复,重新编译并滚动发布。

其它 EC 相关的 JIRA

最近还有如下和 EC 相关且值得关注的 JIRA:

  • HDFS-16422:Fix thread safety of EC decoding during concurrent preads

  • HDFS-16333:fix balancer bug when transfer an EC block

  • HDFS-16268:Balancer stuck when moving striped blocks due to NP


从目前看,虽然一些一二线大厂在生产环境使用 HDFS EC,社区也在不断修复 EC 相关的 bug,但 HDFS EC 本身仍可能存在一些安全隐患,因此建议只对不太重要的冷数据设置 EC 策略,而这些数据要么能通过上游恢复,要么即使丢失也不对生产业务造成任何影响。


识别二维码关注

网站 - https://qileq.com
新浪微博 - @qileq