HDFS EC Reconstruction

HDFS 块重构和RedundancyMonitor详解 本文主要讲解整个块的重构过程,包括: - NameNode端待重构块的生成过程(包含了各种待重构的情况), - NameeNode端基于生成的待重构块进行重构工作的调度, - DataNode端对于重构任务的处理。由于基于副本复制的冗余策略基本上就是数据的拷贝,比较简单,因此,本文偏向于讲解基于纠删码的冗余策略的DataNode端的处理过程。 阅读详情

hdfs ec重构块的代码设计巧妙,本文总结其设计思想。
下文先分析DN重构块的流程。
DN收到NN下达的命令后,判断如果是 BlockECReconstructionCommand 命令,DN则开始重构工作。

// BPOfferService.java
case DatanodeProtocol.DNA_ERASURE_CODING_RECONSTRUCTION:
  LOG.info("DatanodeCommand action: DNA_ERASURE_CODING_RECOVERY");
  Collection<BlockECReconstructionInfo> ecTasks =
      ((BlockECReconstructionCommand) cmd).getECTasks(); //1
  dn.getErasureCodingWorker().processErasureCodingTasks(ecTasks); //2
  break;

我们看一下重构的对象 Collection ecTasks 的结构,包括块组id和源及目标DN信息等:

public static class BlockECReconstructionInfo {
 private final ExtendedBlock block;
 private final DatanodeInfo[] sources;
 private DatanodeInfo[] targets;
 private String[] targetStorageIDs;
 private StorageType[] targetStorageTypes;
 private final byte[] liveBlockIndices;
 private final ErasureCodingPolicy ecPolicy;
 ...

dn.getErasureCodingWorker()获得 private ErasureCodingWorker ecWorker; 那么,ecWorker是一个什么角色呢?我们看定义:

/**
 * ErasureCodingWorker handles the erasure coding reconstruction work commands.
 * These commands would be issued from Namenode as part of Datanode's heart beat
 * response. BPOfferService delegates the work to this class for handling EC
 * commands.
 */
public final class ErasureCodingWorker {
  private static final Logger LOG = DataNode.LOG;
 
  private final DataNode datanode;
  private final Configuration conf;
  private final float xmitWeight;
 
  private ThreadPoolExecutor stripedReconstructionPool;
  private ThreadPoolExecutor stripedReadPool;

ErasureCodingWorker 用于处理EC的重构命令,该命令是NN给DN的心跳回复。

ECWorker在整个架构中的角色如下图所示,用于服务DN有关块构建恢复工作。
在这里插入图片描述
在这里插入图片描述
线程池篇

我们看一下ecWorker中的两个线程池:

  • private ThreadPoolExecutor stripedReconstructionPool;
  • private ThreadPoolExecutor stripedReadPool;

看线程池的初始化:

  // ErasureCodingWorker#initializeStripedReadThreadPool
  private void initializeStripedReadThreadPool() {
    LOG.debug("Using striped reads");

    // Essentially, this is a cachedThreadPool.
    stripedReadPool = new ThreadPoolExecutor(0, Integer.MAX_VALUE,
        60, TimeUnit.SECONDS,
        new SynchronousQueue<>(),
        new Daemon.DaemonFactory() {
          private final AtomicInteger threadIndex = new AtomicInteger(0);
          @Override
          public Thread newThread(Runnable r) {
            Thread t = super.newThread(r);
            t.setName("stripedRead-" + threadIndex.getAndIncrement());
            return t;
          }
        },
        new ThreadPoolExecutor.CallerRunsPolicy() {
          @Override
          public void rejectedExecution(Runnable runnable,
                                        ThreadPoolExecutor e) {
            LOG.info("Execution for striped reading rejected, "
                + "Executing in current thread");
            // will run in the current thread
            super.rejectedExecution(runnable, e);
          }
        });

    stripedReadPool.allowCoreThreadTimeOut(true);
  }

队列使用了无界的new SynchronousQueue<>();使用线程工厂来命名;使用默认的自定义拒绝策略(仅仅打印log,该策略也会执行线程)。核心线程在allowCoreThreadTimeout被设置为true时会超时退出,默认情况下不会退出。当线程空闲时间达到keepAliveTime(上述为60s),该线程会退出,直到线程数量等于corePoolSize。如果allowCoreThreadTimeout设置为true,则所有线程均会退出直到线程数量为0。

第二个线程池初始化:

  // ErasureCodingWorker#initializeStripedBlkReconstructionThreadPool
  private void initializeStripedBlkReconstructionThreadPool(int numThreads) {
    LOG.debug("Using striped block reconstruction; pool threads={}", numThreads);
    stripedReconstructionPool = DFSUtilClient.getThreadPoolExecutor(2,
        numThreads, 60, new LinkedBlockingQueue<>(),
        "StripedBlockReconstruction-", false);
    stripedReconstructionPool.allowCoreThreadTimeOut(true);
  }
  
  //上述封装了getThreadPool方法,放在Util中,如下:
  // DFSUtilClient#getThreadPoolExecutor
  public static ThreadPoolExecutor getThreadPoolExecutor(
      int corePoolSize,
      int maxPoolSize, 
      long keepAliveTimeSecs, 
      BlockingQueue<Runnable> queue,
      String threadNamePrefix, 
      boolean runRejectedExec) {
    Preconditions.checkArgument(corePoolSize > 0);
    ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(corePoolSize,
        maxPoolSize, keepAliveTimeSecs, TimeUnit.SECONDS,
        queue, new Daemon.DaemonFactory() {
          private final AtomicInteger threadIndex = new AtomicInteger(0);

          @Override
          public Thread newThread(Runnable r) {
            Thread t = super.newThread(r);
            t.setName(threadNamePrefix + threadIndex.getAndIncrement());
            return t;
          }
        });
    if (runRejectedExec) {
      threadPoolExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor
          .CallerRunsPolicy() {
        @Override
        public void rejectedExecution(Runnable runnable,
            ThreadPoolExecutor e) {
          LOG.info(threadNamePrefix + " task is rejected by " +
                  "ThreadPoolExecutor. Executing it in current thread.");
          // will run in the current thread
          super.rejectedExecution(runnable, e);
        }
      });
    }
    return threadPoolExecutor;
  }  

封装了get线程池方法,总体还是一样。拒绝策略传入false,不设策略,及即使用默认策略:

/**
 * The default rejected execution handler
 */
 private static final RejectedExecutionHandler defaultHandler = new AbortPolicy();
 

线程池初始化后,看下线程池提交线程的流程:

  public void processErasureCodingTasks(
      Collection<BlockECReconstructionInfo> ecTasks) {
    for (BlockECReconstructionInfo reconInfo : ecTasks) {
      int xmitsSubmitted = 0;
      try {
        StripedReconstructionInfo stripedReconInfo =
            new StripedReconstructionInfo(
            reconInfo.getExtendedBlock(), reconInfo.getErasureCodingPolicy(),
            reconInfo.getLiveBlockIndices(), reconInfo.getSourceDnInfos(),
            reconInfo.getTargetDnInfos(), reconInfo.getTargetStorageTypes(),
            reconInfo.getTargetStorageIDs());
        // It may throw IllegalArgumentException from task#stripedReader
        // constructor.
        final StripedBlockReconstructor task =
            new StripedBlockReconstructor(this, stripedReconInfo);
        if (task.hasValidTargets()) {
          // See HDFS-12044. We increase xmitsInProgress even the task is only
          // enqueued, so that
          //   1) NN will not send more tasks than what DN can execute and
          //   2) DN will not throw away reconstruction tasks, and instead keeps
          //      an unbounded number of tasks in the executor's task queue.
          xmitsSubmitted = Math.max((int)(task.getXmits() * xmitWeight), 1);
          getDatanode().incrementXmitsInProcess(xmitsSubmitted);
          stripedReconstructionPool.submit(task);
        } else {
          LOG.warn("No missing internal block. Skip reconstruction for task:{}",
              reconInfo);
        }
      } catch (Throwable e) {
        getDatanode().decrementXmitsInProgress(xmitsSubmitted);
        LOG.warn("Failed to reconstruct striped block {}",
            reconInfo.getExtendedBlock().getLocalBlock(), e);
      }
    }
  }

在这里插入图片描述
提交到线程池后,接下来就交给了StripedBlockReconstructor implements Runnable的run()。

  //StripedBlockReconstructor#run
  public void run() {
    try {
      initDecoderIfNecessary();

      getStripedReader().init();

      stripedWriter.init();

      reconstruct();

      stripedWriter.endTargetBlocks();

      // Currently we don't check the acks for packets, this is similar as
      // block replication.
    } catch (Throwable e) {
      LOG.warn("Failed to reconstruct striped block: {}", getBlockGroup(), e);
      getDatanode().getMetrics().incrECFailedReconstructionTasks();
    } finally {
      getDatanode().decrementXmitsInProgress(getXmits());
      final DataNodeMetrics metrics = getDatanode().getMetrics();
      metrics.incrECReconstructionTasks();
      metrics.incrECReconstructionBytesRead(getBytesRead());
      metrics.incrECReconstructionRemoteBytesRead(getRemoteBytesRead());
      metrics.incrECReconstructionBytesWritten(getBytesWritten());
      getStripedReader().close();
      stripedWriter.close();
      cleanup();
    }
  }
【HDFS】EC重构过程中的校验功能:DecodingValidator 阅读详情

相关推荐

【信息科学与工程学】【产品体系】第二十七篇 存储系统系列一 01

存储系统是一个横跨单机引擎 → 分布式系统 → 硬件指令集 → 云上多地域的四层技术栈。下面按你给的格式,用一组相互关联的表把"各类特性组合"一次性铺开。版本号以各厂商当前 GA 版本为准,功能清单为生产级能力摘要。编号存储系统(厂商 / 内核 / 引擎 / 版本 / 功能清单)S01Ceph(Red Hat / 自研内核模块 / RADOS + BlueStore + RocksDB / Squid 19.x)/ 功能:RBD 块、RGW 对象(S3/Swift)、CephFS POSIX、副本+EC 混

weixin_49199313的博客 365

HDFS EC文件损坏恢复方法

恢复思路,屏蔽损坏的datanode节点,强制数据从好节点上读取,这里需要用到hdfs api的方式处理,修改了hdfs client的逻辑,增加skip ip参数进行跳过损坏的ip。是在进行读数据的时候发现数据损坏,这是很严重的问题。然后再对文件进行验证,目前我实现了 orc parquet text textGzip的表验证,如果验证到最后,还是不能读取则文件确实损坏了3个节点的数据。如果坏块没有全部损坏,比如RS-3-2-1024K的,只有2个节点损坏,这种情况还是能恢复的。

偏执狂才能生存!热忱比专业知识更重要......... 501

【信息科学与工程学】计算机科学与自动化——第三百零五篇 数据中心 Scale-Up、Scale-Out、Scale-Across 01

临界带宽B_critical满足:V_orig/B_critical = V_orig/(r·B_critical) + V_orig/R_compress + r·V_orig/R_decompress ⇒ 1/B_critical = 1/(r·B_critical) + 1/R_compress + r/R_decompress ⇒ B_critical = (1 - 1/r) / (1/R_compress + r/R_decompress)。T_original中所有数据均经内存总线传输。

weixin_49199313的博客 474

滴滴: HDFS3.0 EC实践案例

HDFS 3.0 新特性 EC 纠删码 实践案例 EC落地实践

Pushkin.的博客 1103

【信息科学与工程学】计算机科学与自动化-——第十五篇云计算 12 公有云里的“多Region + 多AZ“ 02 运营算法01

算法逐步思考推理思考(含数学方程式、对象、资源、任务、进程/协程/线程及对应的代数、约束、目标函数/传递函数/依赖函数、参数及参数的数值范围及边界条件、逐步推理的数学方程式列表、上下文切换、并发/串行/随机/乱序/顺序)算法逐步思考推理思考(含数学方程式、对象、资源、任务、进程/协程/线程及对应的代数、约束、目标函数/传递函数/依赖函数、参数及参数的数值范围及边界条件、逐步推理的数学方程式列表、上下文切换、并发/串行/随机/乱序/顺序)云厂商提高闲置资源利用率。算法复杂度为O(N),N为实例数量。

weixin_49199313的博客 279

【HDFS】切主后关于BlockManager中几个队列(例如pendingReconstruction)的初始化

【HDFS】切主后关于BlockManager中几个队列(例如pendingReconstruction)的初始化

LifeIsGood 416

HDFS的EC(Erasure Coding,纠删码)和块管理

介绍了HDFS的块管理策略,既有基于复制的块管理,也重点介绍了HDFS的纠删码的具体实现,主要偏向于代码解析,同时还有基于实验对一些问题的解答。

小昌昌的博客 3098

单细胞分析实战:当Seurat的SCTransform遇上Harmony,我的整合流程优化笔记

本文详细介绍了单细胞转录组数据分析中SCTransform与Harmony整合流程的优化策略。通过实战案例展示如何调整SCTransform参数、优化Harmony整合效果,并解决常见问题,帮助研究者获得更可靠的生物学发现。特别适合需要处理批次效应的单细胞数据分析人员。

weixin_42552716的博客 356

Hadoop 3.1.3学习笔记2

Hadoop3.1.3学习笔记2 本文主要探讨StripedBlockReconstruction过程,即条带化存储下如何恢复损坏的block,以下内容涉及StripedReader、StripedWriter等相关类的内容,将在后面进行介绍 /** * StripedBlockReconstructor reconstruct one or more missed striped block in * the striped block group, the minimum number of liv

u014245138的博客 492

Linux内核模块开发实战指南(2025版)

2025年Linux内核模块开发迎来革命性突破!本文将从零开始手把手教你构建可动态加载的AI加速驱动模块,揭秘最新内核特性与开发技巧,更包含独家性能调优方案与跨架构移植秘籍。文末附赠价值百万的调试脚本,助你轻松突破开发瓶颈!

资深全栈架构师,乐于在 优快云 分享技术见解,与大家携手共进,共攀技术巅峰! 1806

robomimic实验复现全流程指南:从数据集下载到训练视频生成

本文提供了RoboMimic实验复现的完整实战指南,重点解析了从数据集下载、配置文件定制到模型训练与评估的全流程。以tool_hang任务为例,详细说明了环境准备、数据获取、训练监控及视频生成等关键步骤,并针对常见问题给出了排查方案,帮助研究者高效完成机器人模仿学习实验的闭环验证。

2w3e4r5t6y的博客 1031

HDFS EC:将纠删码技术融入HDFS

本文转自优快云首页。原文链接: http://geek.youkuaiyun.com/news/detail/77338#rd?sukey=3903d1d3b699c208333d632e530c4b9744c5834feb52eec1adcedb583708afb26c596ca9b398a05871e4b84beac2f9e4 在HDFS中,可靠性通过多副本的方式来实现,从而较低

icycode的专栏 1582

学习 Bootstrap 5 之 Tables

学习 Bootstrap 5 之 表格表格 (Tables)1. 创建表格(1). 使用原生的表格标签(2). 使用Bootstrap 5 的提供的表格标签类(3). 原生与Bootstrap创建出来的表格的对比2. 表格样式(1). 表格样式的效果(2). 表格样式的使用1). 用于 <table> 标签2). 用于 <thead> <tbody> <tfoot> 标签 表格 (Tables) 1. 创建表格 (1). 使用原生的表格标签 <tabl

qq_37354060的博客 2130

Towards In-network Acceleration of Erasure Coding(SOSR2020)参考计算分流

什么网内 switch 怎么网内加速传输的过程中加速是否会减少数据量的传输 减少了数据量的传输,在switch上做了计算 io占用变少了 修复率增高 中间出现问题的时候没有中断流量的传输 加速到什么程度,解决的是吞吐量的problem 跟流水线比了吗 没有跟流水线比较 在分布式存储系统中,擦除编码(EC)是一项关键技术,可实现比数据复制更低的存储开销并具有更高的容错能力。 EC可以通过从幸存的计算机中下载奇偶校验数据来重建丢失的数据。 存在的问题:EC请求端IO多路复用,导致数据重建速度大大降低。 在本文中

weixin_41523437的博客 392

宜搭子表单(自定义页面全部展示)

效果:增加自定义页面添加表格组件,配置数据源变量: formUuid'表单编码'变量: pageSize10变量: currentPage1。

2301_80286061的博客 2275

audio语音相关的基础知识-VAD,ASR,AEC,AGC,BF等

有音素之间的间隙,也有静音和语音本身的间隙,为了对数据从时间上进行相对的校准,语音端点检测技术就应运而生了,因此端点检测技术可以决定这种校准的相对精度,使得同一内容的特征更趋于相同,当然,一般情况下是不可能完全相同的。盲源分离的目的是求得源信号的最佳估计,盲辨识的目的是求得传输通道的。这个技术的主要任务是从带有噪声的语音中准确的定位出语音的开始和结束点,因为语音中含有很长的静音,也就是把静音和实际语音分离开来,因为是语音数据的原始处理,所以VAD是语音信号处理过程的关键技术之一。呈现出与会者清晰的声音。

u013250861的博客 1033

Hadoop集群破坏试验可靠性验证

测试结果说明:   集群环境说明: 主机名 IP地址 操作系统版本 Hadoop版本 Hbase版本 Zookeeper版本 机器用途 hadoop1 192.168.3.65 Linux AS 4.8 hadoop-0.20.2 hbase-0.90.4 zookeeper-3.3.3 namenode hadoop2 192.16

刘瑞东的专栏 1954

YOLOv12改进前必看 - YAML模型配置文件详细解读(再也不用担心通道数不匹配) 附网络结构图

YOLOv12的模型配置文件在中,里面包含yolov12的以及的不同大小的模型,本文将详细介绍一下YOLOv12模型文件中各参数的含义。

Limiiiing的博客 3275

HDFS 纠删码 EC

目的 复制是昂贵的 - HDFS中的默认3x 复制方案在存储空间和其他资源(例如,网络带宽)上有 200%的开销。但是,对于具有较低 I/O 活动的暖数据集和冷数据集,在正常操作期间很少访问其他块副本,但仍然消耗与第一个副本相同的资源。 ...

主要写大数据集群一线运维和学习工作经验 2154

手把手教你用git上传项目到GitHub(图文并茂,这一篇就够了),相信你一定能成功!!

GitHub是基于git实现的代码托管。git是目前最好用的版本控制系统了,非常受欢迎,比之svn更好。 GitHub可以免费使用,并且快速稳定。即使是付费帐户,每个月不超过10美刀的费用也非常便宜。 利用GitHub,你可以将项目存档,与其他人分享交流,并让其他开发者帮助你一起完成这个项目。优点在于,他支持多人共同完成一个项目,因此你们可以在同一页面对话交流。 创建自己的项目,并备份,代码不需要保存在本地或者服务器,GitHub做得非常理想。 学习Git也有很多好处。他被视为一个预先维护过程,你可以按自己

左手の明天的博客 3万+

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

HDFS文件的读写流程

HDFS 文件上传流程 详细步骤解析: client 发起文件上传请求,通过 RPC 与 NameNode 建立通讯,NameNode 检查目标文件是否存在,父目录是否存在,返回是否可以上传; client 请求第一个 block 该传输 ...

KILITOH的博客 297

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

HDFS知识点总结

学习完Hadoop权威指南有一段时间了,现在再回顾和总结一下HDFS的知识点。 1、HDFS的设计 HDFS是什么:HDFS即Hadoop分布式文件系统(Hadoop Distributed Filesystem),以流式数据访问模式来存储超大文件,运行于商用硬件集群上,是管理网络中跨多台计算机存储的文件系统。 HDFS不适合用在:要求低时间延迟数据访问的应用,存储大量的小文件,多用户写入,...

weixin_30387423的博客 359

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

Hadoop中datanode故障问题

当向datanode写数据的过程中发现datanode存在故障时,namenode会重新分配一个datanode个pipline进行写操作,这个datanode如果故障了,这上面的block没有了,其他datanode上还有这个block的备份,不过现在该block在系统中的总备份数为2,(坏了一个),下次hdfs使到该块时,会检测到该块的备份数为2,会重新备份让replication数达到3...

很吵请安静 3262

hadoop破坏试验可靠性验证

Hadoop集群环境测试报告   测试结果说明:   集群环境说明: 主机名 IP地址 操作系统版本 Hadoop版本 Hbase版本 Zookeeper版本 机器用途 hadoop1 192.168.3.65 Linux AS 4.8 hadoop-0.20.2

shaozhi_jinni的专栏 1570

学习总结 - 纠删码Erasure Coding (分布式存储系统)

纠删码 Erasure coding纠删码技术简称EC,是一种数据保护技术。最早用于通信行业中数据传输中的数据恢复,是一种编码容错技术。他通过在原始数据中加入新的校验数据,使得各个部分的数据产生关联性。在一定范围的数据出错情况下,通过纠删码技术都可以进行恢复。 副本策略和纠删码是存储领域常见的两种数据冗余技术。相比于副本策略,纠删码具有更高的磁盘利用率 多副本策略即将数据存储多个副本(一...

tianyeshiye 4711

Erasure Coding(纠删码)深入分析

原文地址:Coding(纠删码)深入分析" style="text-decoration:none; color:rgb(42,112,155)">Erasure Coding(纠删码)深入分析作者:Eric雪菲 1.前言 Swift升级到2.0大版本后宣称开始支持纠删码,这其实是一个很有意义的特性,主要是能够在一定程度上解决3副本空间浪费太多的问题。因为3副本这一点是swift推

算法之道 4876
上一篇: HDFS中的优秀的多线程设计
下一篇: ZKFC原理解析
王小禾
博客等级 码龄11年 80粉丝 291原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值