hdfs dn锁拆分

一、当前实现及问题

HDFS社区版本中DN内部使用了一把全局锁,volume操作之间的并发能力受到制约。

当前使用的锁为AutoCloseableLock,实际上就是一个ReentrantLock

public class AutoCloseableLock implements AutoCloseable {

  private final Lock lock;
  public AutoCloseableLock() {
    this(new ReentrantLock());
  }

  public AutoCloseableLock(Lock lock) {
    this.lock = lock;
  }
  public AutoCloseableLock acquire() {
    lock.lock();
    return this;
  }
  public void release() {
    lock.unlock();
  }
  @Override
    public void close() {
    release();
  } 
  //...

涉及的类:

FsDatasetImpl、FsVolumeImpl、ProvidedVolumeImpl、DistBalancer、ReplicaMap、BPServiceActor等

高密度场景下的dn节点,volume越多,原版本带来的锁问题越大:

  • FsDataSet使用全局锁控制volume读写,增加volume个数无疑会增加锁竞争,且会拖慢并行写入的吞吐,降低单机的性能

  • volume增多之后,IBR以及FBR也会相应的增加,这对NN和DN通讯也会带来更大的压力

  • 机器磁盘故障时,影响的数据量级比之前增加很多,需要做到快速恢复

二、优化方案

第一阶段 AutoCloseableLock 改为 ReentrantReadWriteLock

AutoCloseableLock直接使用的是ReentrantLock,改进后使用InstrumentedReadWriteLock,底层通过ReentrantReadWriteLock进行封装实现。对一些DN操作可以使用读锁来提高并发(共享资源被一个线程写入时,其他线程不能读取和写入;共享资源可以被多个线程同时读取)。

可使用读锁的相关功能:

1.Replicamap

该类维护副本的集合。一些方法会调用`replicmap .replicas()`(例如`getBlockReports`, `getFinalizedBlocks`, `deepCopyReplica`),并且只以只读方式使用,所以它们也可以切换到使用readLock。

2.Disk Balancer和Directory Scanner

目录扫描仪和磁盘均衡器,只需要读锁。

3.FsDatasetImpl

FsDatasetImpl中的方法getVolume、getStoredBlock、deepCopyReplica、getTmpInputStreams等都可以改用readLock

类图:

BlockPool-Volume加锁用的AutoCloseDataSetLock,继承了 AutoCloseableLock,通过try-with-resources调用,实现自动释放锁

第二阶段 拆锁

针对全局锁的问题,可以考虑做拆锁方案,减少FsDataSet读写数据时引起的锁竞争与锁等待。

从结构上来看,FsDataSet划分数据有两个层面上的聚合,第一个是BlockPool级别,第二个是Volume级别。

对于federation集群来说,一个集群会有大于一个的BlockPool,BlockPool本身会包含着多volume,结构划分如下:

对于这样的结构划分,考虑拆解为BlockPool级别的(父)锁以及Volume级别的(子)锁。

按照场景确定不同的加锁规则

1.对于一个volume内的数据读写操作,我们需要对该操作加volume级别的读写锁和BlockPool级别的读锁(优化的关键,一个volume内的数据读写,本质上没有改变BlockPool级别的元数据逻辑,因此只需要加读锁)

2.对于多个volume间的数据读写操作,例如dn内部的数据迁移,则需要加BlockPool级别的写锁,此时则不能加volume级别的锁

3.对于BlockPool级别的元数据变更,例如BlockPool清理,BlockPool添加等,这个属于BlockPool级别改动,需要加BlockPool级别的写锁。部分场景下需要加dn进程级别的全局锁

三、社区现状

社区issue:[HDFS-15382] Split one FsDatasetImpl lock to volume grain locks. - ASF JIRA

一共包含 13个子任务,其中9个子任务已解决

done

  • 目前社区已经基本完成锁的拆分,包括实现读写锁 AutoCloseDataSetLock、实现管理类 DataSetLockManager、将全局锁拆分成读写锁(其中锁的拆分在社区是逐步完成的,首先是将所有的锁替换成BLOCK_POOL类型的锁,然后再逐步将锁粒度细化成BLOCK_POOL+VOLUME),此外也解决了已知的死锁问题

  • 当前已经将社区所有已完成的子任务及其相关依赖的pr合并,进行了读写性能测试。并且在逻辑层面梳理了所有改造相关的加锁流程,排除了死锁的可能

todo

[HDFS-16657] Changing pool-level lock to volume-level lock for invalidation of blocks - ASF JIRA 当一个非常繁忙的节点上出现block invalidation,这个时候DN正在尝试查找块文件的父路径,因此存在池级锁定中的磁盘 I/O。当磁盘变得非常繁忙且 io 等待时间长时,所有待处理线程都会被 pool 级锁阻塞,心跳时间高。这个issue有被讨论,下一步可能有意向去搞

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值