`
iwinit
  • 浏览: 454066 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
文章分类
社区版块
存档分类
最新评论

[HBase]abort引发的死锁

阅读更多

今天在HBase群里碰到一个客户端死锁问题,堆栈如下

Java stack information for the threads listed above:
===================================================
"KVQueueService-Handler-2-EventThread":
        at org.apache.hadoop.hbase.zookeeper.ZooKeeperNodeTracker.stop(ZooKeeperNodeTracker.java:98)
        - waiting to lock <0x0000000760ca2680> (a org.apache.hadoop.hbase.zookeeper.RootRegionTracker)
        at org.apache.hadoop.hbase.client.HConnectionManager$HConnectionImplementation.resetZooKeeperTrackers(HConnectionManager.java:605)
        - locked <0x0000000760c88e00> (a org.apache.hadoop.hbase.client.HConnectionManager$HConnectionImplementation)
        at org.apache.hadoop.hbase.client.HConnectionManager$HConnectionImplementation.abort(HConnectionManager.java:1698)
        at org.apache.hadoop.hbase.zookeeper.ZooKeeperWatcher.connectionEvent(ZooKeeperWatcher.java:374)
        at org.apache.hadoop.hbase.zookee
per.ZooKeeperWatcher.process(ZooKeeperWatcher.java:271)
        at org.apache.zookeeper.ClientCnxn$EventThread.processEvent(ClientCnxn.java:521)
        at org.apache.zookeeper.ClientCnxn$EventThread.run(ClientCnxn.java:497)
"TableDataQueueService-Handler-4":
        at org.apache.hadoop.hbase.client.HConnectionManager$HConnectionImplementation.resetZooKeeperTrackers(HConnectionManager.java:600)
        - waiting to lock <0x0000000760c88e00> (a org.apache.hadoop.hbase.client.HConnectionManager$HConnectionImplementation)
        at org.apache.hadoop.hbase.client.HConnectionManager$HConnectionImplementation.abort(HConnectionManager.java:1698)
        at org.apache.hadoop.hbase.zookeeper.ZooKeeperNodeTracker.blockUntilAvailable(ZooKeeperNodeTracker.java:132)
        - locked <0x0000000760ca2680> (a org.apache.hadoop.hbase.zookeeper.RootRegionTracker)
        at org.
apache.hadoop.hbase.zookeeper.RootRegionTracker.waitRootRegionLocation(RootRegionTracker.java:83)
        at org.apache.hadoop.hbase.client.HConnectionManager$HConnectionImplementation.locateRegion(HConnectionManager.java:830)
        at org.apache.hadoop.hbase.client.HConnectionManager$HConnectionImplementation.locateRegion(HConnectionManager.java:810)
        at org.apache.hadoop.hbase.client.HConnectionManager$HConnectionImplementation.locateRegionInMeta(HConnectionManager.java:942)
        at org.apache.hadoop.hbase.client.HConnectionManager$HConnectionImplementation.locateRegion(HConnectionManager.java:841)
        at org.apache.hadoop.hbase.client.HConnectionManager$HConnectionImplementation.locateRegion(HConnectionManager.java:810)
        at org.apache.hadoop.hbase.client.HConnectionManager$HConnectionImplementation.locateRegionInMeta(HConnectionManager.j
ava:942)
        at org.apache.hadoop.hbase.client.HConnectionManager$HConnectionImplementation.locateRegion(HConnectionManager.java:845)
        at org.apache.hadoop.hbase.client.HConnectionManager$HConnectionImplementation.processBatchCallback(HConnectionManager.java:1520)
        at org.apache.hadoop.hbase.client.HConnectionManager$HConnectionImplementation.processBatch(HConnectionManager.java:1376)
        at org.apache.hadoop.hbase.client.HTable.flushCommits(HTable.java:936)
        at org.apache.hadoop.hbase.client.HTable.doPut(HTable.java:792)
        at org.apache.hadoop.hbase.client.HTable.put(HTable.java:775)
        at org.apache.hadoop.hbase.client.HTablePool$PooledHTable.put(HTablePool.java:402)
        at com.alibaba.alimonitor.store.hbase.TableDataDaoService.writeData(TableDataDaoService.java:111)
        at com.alibaba.alimonitor.store.service.Tab
leDataQueueService.handle(TableDataQueueService.java:28)
        at com.alibaba.alimonitor.store.service.TableDataQueueService.handle(TableDataQueueService.java:14)
        at com.alibaba.alimonitor.store.service.AbstractQueueService$HandleThread.run(AbstractQueueService.java:115)

Found 1 deadlock.

 可见发生死锁的业务线程和zookeeper的eventThread线程。EventThread是zookeeper用来通知客户端watcher的线程,它会回调使用者注册的watcher。

在这里,首先是eventThread处理connectionEvent的Expired事件

 case Expired:
        if (ZKUtil.isSecureZooKeeper(this.conf)) {
          // We consider Expired equivalent to AuthFailed for this
          // connection. Authentication is never going to complete. The
          // client should proceed to do cleanup.
          saslLatch.countDown();
        }
        String msg = prefix(this.identifier + " received expired from " +
          "ZooKeeper, aborting");
        // TODO: One thought is to add call to ZooKeeperListener so say,
        // ZooKeeperNodeTracker can zero out its data values.
        if (this.abortable != null) this.abortable.abort(msg,
            new KeeperException.SessionExpiredException());
        break;
    }

 这里会abort调用,其实是调用的HConnectionImplementation的abort方法

 public void abort(final String msg, Throwable t) {
      if (t instanceof KeeperException) {
        LOG.info("This client just lost it's session with ZooKeeper, will"
            + " automatically reconnect when needed.");
        if (t instanceof KeeperException.SessionExpiredException) {
          LOG.info("ZK session expired. This disconnect could have been" +
              " caused by a network partition or a long-running GC pause," +
              " either way it's recommended that you verify your environment.");
          resetZooKeeperTrackers();
        }
        return;
      }
      if (t != null) LOG.fatal(msg, t);
      else LOG.fatal(msg);
      this.aborted = true;
      close();
    }

 再看resetZooKeeperTrackers方法,是一个同步方法,EventThread在这里拿到HConnectionImplementation对象锁

    private synchronized void resetZooKeeperTrackers() {
      if (masterAddressTracker != null) {
        masterAddressTracker.stop();
        masterAddressTracker = null;
      }
      if (rootRegionTracker != null) {
        rootRegionTracker.stop();
        rootRegionTracker = null;
      }
      clusterId = null;
      if (zooKeeper != null) {
        zooKeeper.close();
        zooKeeper = null;
      }
    }

 这个时候业务线程开始region location,进入RootRegionTrack的waitRootRegionLocation

  public ServerName waitRootRegionLocation(long timeout)
  throws InterruptedException {
    if (false == checkIfBaseNodeAvailable()) {
      String errorMsg = "Check the value configured in 'zookeeper.znode.parent'. "
          + "There could be a mismatch with the one configured in the master.";
      LOG.error(errorMsg);
      throw new IllegalArgumentException(errorMsg);
    }
    return dataToServerName(super.blockUntilAvailable(timeout, true));
  }

 业务线程进入blockUntilAvailable,拿到父类ZookeeperNodeTracker的对象锁

public synchronized byte [] blockUntilAvailable(long timeout, boolean refresh)
  throws InterruptedException {
    if (timeout < 0) throw new IllegalArgumentException();
    boolean notimeout = timeout == 0;
    long startTime = System.currentTimeMillis();
    long remaining = timeout;
    if (refresh) {
      try {
	//这里正好抛出异常
        this.data = ZKUtil.getDataAndWatch(watcher, node);
      } catch(KeeperException e) {
        abortable.abort("Unexpected exception handling blockUntilAvailable", e);
      }
    }
    while (!this.stopped && (notimeout || remaining > 0) && this.data == null) {
      // We expect a notification; but we wait with a
      //  a timeout to lower the impact of a race condition if any
      wait(100);
      remaining = timeout - (System.currentTimeMillis() - startTime);
    }
    return this.data;
  }

 由于这里zookeeper调用正好抛出异常导致业务线程去abort,这个时候因为EventThread已经先abort了,所以业务线程需要等待HConnectionImplementation对象锁的释放。而这个时候EventThread继续执行,resetZooKeeperTrackers中继续调用 rootRegionTracker.stop()方法

 public synchronized void stop() {
    this.stopped = true;
    notifyAll();
  }

 这个方法需要拿到父类ZookeeperNodeTracker的对象锁,而此时这个锁已经被业务线程拿到了,这就发生了死锁。根本原因abort操作没有做并发控制。最新版本的hbase已经修复了这个bug,修复后的abort方法,增加了resetting同步状态,后续abort请求直接return了。

public void abort(final String msg, Throwable t) {
      if (t instanceof KeeperException) {
        LOG.info("This client just lost it's session with ZooKeeper, will"
            + " automatically reconnect when needed.");
        if (t instanceof KeeperException.SessionExpiredException) {
          LOG.info("ZK session expired. This disconnect could have been" +
              " caused by a network partition or a long-running GC pause," +
              " either way it's recommended that you verify your environment.");
          //同步状态
          synchronized (resetLock) {
            if (resetting) return;
            this.resetting = true;
          }
          resetZooKeeperTrackers();
          this.resetting = false;
        }
        return;
      }
      if (t != null) LOG.fatal(msg, t);
      else LOG.fatal(msg);
      this.aborted = true;
      close();
    }

 官方issue地址 https://issues.apache.org/jira/browse/HBASE-7259

分享到:
评论

相关推荐

    HbaseTemplate 操作hbase

    在IT行业中,尤其是在大数据处理领域,HBase是一个广泛使用的分布式、高性能、列式存储的NoSQL数据库。HBase是建立在Hadoop文件系统(HDFS)之上,为处理大规模数据提供了一个高效的数据存储解决方案。而Spring Data...

    pinpoint的hbase初始化脚本hbase-create.hbase

    搭建pinpoint需要的hbase初始化脚本hbase-create.hbase

    hbase用于查询客户端工具

    HBase是一种分布式、基于列族的NoSQL数据库,它在大数据领域中扮演着重要的角色,尤其是在需要实时查询大规模数据集时。HBase以其高吞吐量、低延迟和水平扩展能力而闻名,常用于存储非结构化和半结构化数据。在HBase...

    hbase配置内置的zookeeper

    ### HBase 配置内置 ZooKeeper 的详细步骤与解析 #### 一、配置背景与目的 在 HBase 的部署环境中,ZooKeeper 起着非常重要的作用,它主要用于协调集群中的各个节点,并且管理 HBase 的元数据。通常情况下,HBase ...

    HBase(hbase-2.4.9-bin.tar.gz)

    HBase(hbase-2.4.9-bin.tar.gz)是一个分布式的、面向列的开源数据库,该技术来源于 Fay Chang 所撰写的Google论文“Bigtable:一个结构化数据的分布式存储系统”。就像Bigtable利用了Google文件系统(File System...

    HBase开启审计日志

    ### HBase开启审计日志详解 #### 一、概述 HBase是一款分布式列式存储系统,基于Google的Bigtable论文实现。它具有高可靠性、高性能、面向列、可伸缩的特点,非常适合处理海量数据。在大数据领域,HBase被广泛用于...

    Hbase权威指南(HBase: The Definitive Guide)

    ### HBase权威指南知识点概述 #### 一、引言与背景 - **大数据时代的来临**:随着互联网技术的发展,人类社会产生了前所未为的数据量。这些数据不仅数量巨大,而且种类繁多,传统的数据库系统难以应对这样的挑战。 ...

    基于springboot集成hbase过程解析

    "基于SpringBoot集成HBase过程解析" SpringBoot集成HBase是当前大数据处理和存储解决方案中的一种常见组合。HBase是基于Hadoop的分布式、可扩展的NoSQL数据库,能够存储大量的结构化和非结构化数据。SpringBoot则...

    hbase安装与使用

    ### HBase 安装与使用知识点详解 #### 概述 HBase 是一款构建于 Hadoop 之上的分布式、可扩展的大规模数据存储系统。它提供了类似 Google BigTable 的功能特性,非常适合处理海量数据和高并发读写需求的应用场景。...

    HBase学习利器:HBase实战

    ### HBase学习利器:HBase实战 #### 一、HBase简介与背景 HBase是Apache Hadoop生态系统中的一个分布式、可扩展的列族数据库,它提供了类似Bigtable的能力,能够在大规模数据集上进行随机读写操作。HBase是基于...

    hbase安装包

    HBase,全称为Hadoop Distributed File System上的基础结构(HBase on Hadoop Distributed File System),是一种分布式的、面向列的开源数据库,它构建在Apache Hadoop文件系统(HDFS)之上,提供高可靠性、高性能...

    hbase-2.4.17-bin 安装包

    HBase是Apache Hadoop生态系统中的一个分布式、版本化、列族式存储系统,设计用于处理大规模数据集。这个“hbase-2.4.17-bin”安装包提供了HBase的最新稳定版本2.4.17,适用于大数据处理和分析场景。下面将详细介绍...

    hbase 资源合集 hbase 企业应用开发实战 权威指南 hbase 实战 hbase 应用架构

    《HBase资源合集》包含了四本重量级的书籍,分别是《HBase企业应用开发实战》、《HBase权威指南》、《HBase实战》以及《HBase应用架构》。这些书籍深入浅出地探讨了HBase在大数据环境中的应用与开发,是学习和掌握...

    CDH-Hbase的安装1

    在本文中,我们将深入探讨HBase的安装过程及其在CDH环境中的集成。HBase是Apache Hadoop生态系统中的一个核心组件,它是一个分布式、版本化的、支持列族的NoSQL数据库,特别适合处理大规模的数据存储。CDH(Cloudera...

    scala API 操作hbase表

    在本文中,我们将深入探讨如何使用Scala API操作HBase数据库。HBase是一个分布式、面向列的NoSQL数据库,它构建于Hadoop之上,提供实时访问大量数据的能力。Scala是一种强大的函数式编程语言,与Java虚拟机(JVM)...

    hbase数据可视化系统

    《HBase数据可视化系统构建详解》 在大数据领域,HBase作为一款分布式列式数据库,因其高并发、低延迟和大规模存储的特点,被广泛应用在实时数据处理和分析中。然而,对于非技术人员来说,直接操作HBase命令行进行...

    Hbase可视化客户端.rar

    HBase是一款基于Google Bigtable设计的开源分布式数据库,属于Apache Hadoop项目的一部分。它是一个高可靠性、高性能、列式存储、支持多版本、实时的分布式数据库,特别适合于处理海量结构化半结构化数据。HBase主要...

    hbase-sdk是基于hbase-client和hbase-thrift的原生API封装的一款轻量级的HBase ORM框架

    hbase-sdk是基于hbase-client和hbase-thrift的原生API封装的一款轻量级的HBase ORM框架。 针对HBase各版本API(1.x~2.x)间的差异,在其上剥离出了一层统一的抽象。并提供了以类SQL的方式来读写HBase表中的数据。对...

    HBase源代码 hbase-0.98.23

    《深入剖析HBase源代码:hbase-0.98.23》 HBase,作为Apache的一个开源项目,是构建在Hadoop之上的分布式、版本化、列族式的NoSQL数据库,它提供了高可靠性、高性能、可伸缩的数据存储解决方案。本文将基于hbase-...

Global site tag (gtag.js) - Google Analytics