当前位置: 首页 > article >正文

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有被讨论,下一步可能有意向去搞


http://www.kler.cn/a/284391.html

相关文章:

  • 机器学习【激活函数】
  • 【AI日记】24.11.14 复习和准备 RAG 项目 | JavaScript RAG Web Apps with LlamaIndex
  • 力扣662:二叉树的最大宽度
  • 2024年11月12日Github流行趋势
  • HBase使用create创建表时报错ERROR: KeeperErrorCode = NoNode for /hbase/master
  • 论文解析:边缘计算网络中资源共享的分布式协议(2区)
  • 【记忆回溯】【深度搜索】【动态规划】【字符串】【力扣】单词拆分
  • Hive SQL 练习
  • 2024 年的 Web3 游戏:演变、趋势和市场动态
  • 【云游戏】点量云流赋能大型游戏新体验
  • MP条件构造器之常用功能详解(or、and、exists、notExists)
  • 【机器学习】9. softmax(Multinomial Logistic Regression)
  • SQL数据库教案(入门必备)
  • 【C++ 第十六章】哈希
  • C# 弹出USB移动存储设备【附源码】
  • 假如我是前端面试官
  • 解决移动端使用Vant van-overlay 遮罩层导致的弹窗不可滚动问题
  • Linux 非root用户部署elasticsearch 7.17.23和ik分词器
  • cnocr 安装
  • 华为云征文|Flexus云服务器搭建基础环境
  • 聚合函数的艺术:SQL中的SUM、AVG、MAX、MIN深度解析
  • JavaScript在网页设计
  • LuaJit分析(六)luajit -bl 命令分析
  • OpenCV几何图像变换(11)极坐标转换函数warpPolar()的使用
  • 微服务事务管理
  • 计网_整体概念逻辑简单过一遍