[DN优化] [锁优化] [HDFS-15150] Introduce read write lock to Datanode

分析

背景:DN性能优化的一部分
目标:AutoCloseableLock 改为 ReadWriteLock

知识回顾:假设在程序中定义一个共享的数据结构,它大部分时间提供读服务,而写操作占有的时间很少,但是写操作完成之后的更新需要对后续的读服务可见。在没有写操作的时候,两个线程同时读一个资源没有任何问题,所以应该允许多个线程能在同时读取共享资源。但是如果有一个线程想去写这些共享资源,就不应该再有其它线程对该资源进行读或写(也就是说:读-读能共存,读-写不能共存,写-写不能共存)。这就需要一个读/写锁来解决这个问题。

ReentrantReadWriteLock的实现里面重要特性:1、公平性:非公平锁(默认):非公平锁的吞吐量要高于公平锁。(公平锁概念:公平锁利用AQS的CLH队列,释放当前保持的锁时,优先为等待时间最长的那个写操作分配写入锁)

代码实现

Hadoop自定义实现了一套支持try-with-resource的锁。如下:

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();
  } 
  //...

当然上述只是文本的背景,只是指出在代码中会使用try-with-resource

锁的改动如下:

在这里插入图片描述
直接将 datasetLock 改为 datasetWriteLock 和 datasetReadLock。排它锁则新定义一个datasetRWLock。

在这里插入图片描述

原来的datasetLock直接使用的是ReentrantLock,改进后使用InstrumentedReadWriteLock。

在使用的时候:

volumeMap = new ReplicaMap(datasetLock);

改为:

volumeMap = new ReplicaMap(datasetRWLock);
private void activateVolume(
    ReplicaMap replicaMap,
    Storage.StorageDirectory sd, StorageType storageType,
    FsVolumeReference ref) throws IOException {
  try (AutoCloseableLock lock = datasetLock.acquire()) {

改为:

private void activateVolume(
    ReplicaMap replicaMap,
    Storage.StorageDirectory sd, StorageType storageType,
    FsVolumeReference ref) throws IOException {
  try (AutoCloseableLock lock = datasetWriteLock.acquire()) {

那么会影响到哪些方法呢:

  • 对于FsVolumeImpl类,全部都是由datasetLock 改为datasetWriteLock,对于改为writeLock的地方,基本无影响;volumeMap = new ReplicaMap(datasetLock);改为 volumeMap = new ReplicaMap(datasetRWLock);基本无影响。
  • ProvidedVolumeImpl类中 bpVolumeMap = new ReplicaMap(new AutoCloseableLock()); 改为 bpVolumeMap = new ReplicaMap(new ReentrantReadWriteLock());
  • 在ReplicaMap类中全都改为writeLock,基本不影响。

总结:

review全部的改动点,都是将排它锁改为读写锁中的写锁,其实达到的效果是一样的,并没有达到拆锁的目的,不会提升性能。为什么要这样改动呢?看原文:

The first conservative step, would be to change the current lock and then make all accesses to it obtain the write lock. That way, we should keep the current behaviour and then we can selectively move some lock accesses to the readlock in separate Jiras.

简单来说就是拆锁的第一步,保守改动,换锁拆锁但是全部使用写锁,这样达到第一阶段的目的。为后续加入读锁做好准备。

必须要加入后续的PATCH。不然拆锁的效果不能生效。

测试

单元测试通过

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值