HBase源码分析之HRegionServer上的MovedRegionsCleaner工作线程

简介:         MovedRegionsCleaner是什么呢?我们先来看下它在HRegionServer上的定义: /** * Chore to clean periodically the moved region list * 被移动Region列表的定期清理工作线程 */ private MovedRegionsCleaner movedRegionsCleaner;        原来它是HRegionServer上一个被移动Region列表的定期清理工作线程。

        MovedRegionsCleaner是什么呢?我们先来看下它在HRegionServer上的定义:

  /**
   * Chore to clean periodically the moved region list
   * 被移动Region列表的定期清理工作线程
   */
  private MovedRegionsCleaner movedRegionsCleaner;
        原来它是HRegionServer上一个被移动Region列表的定期清理工作线程。而它的类的定义如下:

  /**
   * Creates a Chore thread to clean the moved region cache.
   */
  protected static class MovedRegionsCleaner extends Chore implements Stoppable {
    private HRegionServer regionServer;
    Stoppable stoppable;

    // 私有构造方法
    private MovedRegionsCleaner(
      HRegionServer regionServer, Stoppable stoppable){
      super("MovedRegionsCleaner for region "+regionServer, TIMEOUT_REGION_MOVED, stoppable);
      this.regionServer = regionServer;
      this.stoppable = stoppable;
    }

    // 静态方法,通过其创建MovedRegionsCleaner实例
    static MovedRegionsCleaner createAndStart(HRegionServer rs){
      Stoppable stoppable = new Stoppable() {
        private volatile boolean isStopped = false;
        @Override public void stop(String why) { isStopped = true;}
        @Override public boolean isStopped() {return isStopped;}
      };

      return new MovedRegionsCleaner(rs, stoppable);
    }
  }
        我们发现它继承自Chore类,并且线程工作的频率为TIMEOUT_REGION_MOVED,也就是2分钟。这与之前我们讲过的HRegionServer上检查合并请求的compactionChecker、检查刷新请求的periodicFlusher是一样的,都继承了Chore类。关于Chore类,我们在之前的文章中已经讲过,这里就不再赘述了。

        我们看下它的构造方法,只有一个private的私有构造方法,同时它又提供了一个静态方法createAndStart(),这个方法被HRegionServer调用以构造MovedRegionsCleaner对象。而在HRegionServer中,MovedRegionsCleaner是如此被初始化的,代码如下:

    // Create the thread to clean the moved regions list
    // 创建movedRegionsCleaner工作线程去清理被移动Region列表
    movedRegionsCleaner = MovedRegionsCleaner.createAndStart(this);
        那么,MovedRegionsCleaner线程是如何工作的呢?按照之前讲的,集成自Chore的线程会周期性的调用chore()方法来执行需要做的工作。我们还是看下它的chore()方法,代码如下:

    // chore()方法就是调用HRegionServer的cleanMovedRegions()方法
    @Override
    protected void chore() {
      regionServer.cleanMovedRegions();
    }
        很简单,它实际调用的是regionServer实例的cleanMovedRegions()方法,代码如下:

  /**
   * Remove the expired entries from the moved regions list.
   */
  protected void cleanMovedRegions() {
    
	// 计算超时时间,当前时间减去固定值2分钟
	final long cutOff = System.currentTimeMillis() - TIMEOUT_REGION_MOVED;
    
	// 获取movedRegions集合的迭代器it
	Iterator<Entry<String, MovedRegionInfo>> it = movedRegions.entrySet().iterator();

	// 利用迭代器it遍历movedRegions集合中的元素
    while (it.hasNext()){
    	
      // 取出movedRegions集合中的元素e,它是key-value类型,key为String类型的Region名称,value为MovedRegionInfo
      Map.Entry<String, MovedRegionInfo> e = it.next();
      
      // 根据MovedRegionInfo的MoveTime,即ts,与当前时间比较,
      // 如果当前时间已超过TIMEOUT_REGION_MOVED,则移除,
      // ts实际上是MovedRegionInfo的创建时间,也就是Region被移动的时间
      if (e.getValue().getMoveTime() < cutOff) {
        it.remove();
      }
    }
  }
        逻辑比较清晰,大体如下:

        1、首先计算超时时间,当前时间减去固定值2分钟,赋值给cutOff;

        2、获取movedRegions集合的迭代器it,实际上movedRegions就是HRegionServer上存储已被移动Regions的集合;

        3、利用迭代器it遍历movedRegions集合中的元素:

              3.1、取出movedRegions集合中的元素e,它是key-value类型,key为String类型的Region名称,value为MovedRegionInfo;

              3.2、根据MovedRegionInfo的MoveTime,即ts,与当前时间比较,如果当前时间已超过TIMEOUT_REGION_MOVED,则移除,ts实际上是MovedRegionInfo的创建时间,也就是Region被移动的时间。

        实际上,整个处理流程很简单,而MovedRegionInfo的代码如下:

  private static class MovedRegionInfo {
    private final ServerName serverName;
    private final long seqNum;
    private final long ts;

    public MovedRegionInfo(ServerName serverName, long closeSeqNum) {
      this.serverName = serverName;
      this.seqNum = closeSeqNum;
      ts = EnvironmentEdgeManager.currentTime();
     }

    public ServerName getServerName() {
      return serverName;
    }

    public long getSeqNum() {
      return seqNum;
    }

    public long getMoveTime() {
      return ts;
    }
  }
        其中,就包括一个重要的变量long类型的ts,它在构造方法中被赋值为当前时间,而被移动Region加入movedRegions时,是通过HRegionServer的addToMovedRegions()方法实现的,具体代码如下:

  protected void addToMovedRegions(String encodedName, ServerName destination, long closeSeqNum) {
    if (ServerName.isSameHostnameAndPort(destination, this.getServerName())) {
      LOG.warn("Not adding moved region record: " + encodedName + " to self.");
      return;
    }
    LOG.info("Adding moved region record: "
      + encodedName + " to " + destination + " as of " + closeSeqNum);
    movedRegions.put(encodedName, new MovedRegionInfo(destination, closeSeqNum));
  }
        我们发现,movedRegions集合中,key就是Region的encodedName,而value则是构造的一个对应包含目的地ServerName和关闭序列号closeSeqNum的MovedRegionInfo实例,而MovedRegionInfo在构造时,其ts的赋值上面已经展示了,就是当前时间啊。

        综上所述,MovedRegionsCleaner是HRegionServer上一个工作线程,它周期性的清理已被移动Region列表movedRegions中的到达时间的MovedRegionInfo信息,而线程工作的频率和MovedRegionInfo存活时间,均是TIMEOUT_REGION_MOVED,也就是2分钟。

        至于movedRegions集合中的数据是何时被添加的,为什么又要设计这种模式来移除其中的数据,我们后续再讲!








相关实践学习
lindorm多模间数据无缝流转
展现了Lindorm多模融合能力——用kafka API写入,无缝流转在各引擎内进行数据存储和计算的实验。
云数据库HBase版使用教程
&nbsp; 相关的阿里云产品:云数据库 HBase 版 面向大数据领域的一站式NoSQL服务,100%兼容开源HBase并深度扩展,支持海量数据下的实时存储、高并发吞吐、轻SQL分析、全文检索、时序时空查询等能力,是风控、推荐、广告、物联网、车联网、Feeds流、数据大屏等场景首选数据库,是为淘宝、支付宝、菜鸟等众多阿里核心业务提供关键支撑的数据库。 了解产品详情:&nbsp;https://cn.aliyun.com/product/hbase &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
1月前
|
存储 NoSQL Redis
Redis 新版本引入多线程的利弊分析
【10月更文挑战第16天】Redis 新版本引入多线程是一个具有挑战性和机遇的改变。虽然多线程带来了一些潜在的问题和挑战,但也为 Redis 提供了进一步提升性能和扩展能力的可能性。在实际应用中,我们需要根据具体的需求和场景,综合评估多线程的利弊,谨慎地选择和使用 Redis 的新版本。同时,Redis 开发者也需要不断努力,优化和完善多线程机制,以提供更加稳定、高效和可靠的 Redis 服务。
41 1
|
1月前
线程CPU异常定位分析
【10月更文挑战第3天】 开发过程中会出现一些CPU异常升高的问题,想要定位到具体的位置就需要一系列的分析,记录一些分析手段。
66 0
|
1月前
|
存储 分布式计算 Hadoop
Hadoop-33 HBase 初识简介 项目简介 整体架构 HMaster HRegionServer Region
Hadoop-33 HBase 初识简介 项目简介 整体架构 HMaster HRegionServer Region
53 2
|
5月前
|
存储 SQL 监控
JAVA 线程池的分析和使用
JAVA 线程池的分析和使用
42 0
|
2月前
|
并行计算 API 调度
探索Python中的并发编程:线程与进程的对比分析
【9月更文挑战第21天】本文深入探讨了Python中并发编程的核心概念,通过直观的代码示例和清晰的逻辑推理,引导读者理解线程与进程在解决并发问题时的不同应用场景。我们将从基础理论出发,逐步过渡到实际案例分析,旨在揭示Python并发模型的内在机制,并比较它们在执行效率、资源占用和适用场景方面的差异。文章不仅适合初学者构建并发编程的基础认识,同时也为有经验的开发者提供深度思考的视角。
|
3月前
|
存储 监控 Java
|
3月前
|
安全 Java 开发者
Swing 的线程安全分析
【8月更文挑战第22天】
61 4
|
3月前
|
Java 数据库连接 数据库
当线程中发生异常时的情况分析
【8月更文挑战第22天】
111 4
|
3月前
|
安全 Java 程序员
线程安全与 Vector 类的分析
【8月更文挑战第22天】
55 4
|
3月前
|
存储 缓存 安全
深度剖析Java HashMap:源码分析、线程安全与最佳实践
深度剖析Java HashMap:源码分析、线程安全与最佳实践