首先描述一下现象

最近对HDFS底层做了许多优化,包括硬件压缩卡,内存盘及SSD。

在出测试报告时发现老问题,HBase写入速度不稳定,这个大家都习以为常了吧,就是压测时,只要row size稍小一点,不管你怎么压,HBase的RegionServer总是不愠不火特淡定。有些人就怀疑是磁盘到瓶颈了?还有些人怀疑是不是GC拖累了?

总之网上大部分测试都是黑盒测试嘛,大家也就乱猜呗。

下面我仔细来分析下原因,并解决掉问题,详细的测试数据在http://blog.csdn.net/kalaamong/article/details/7290192,对数据感兴趣的同学可以直接跳过下面的内容。

大概全套问题都解决之后写入通量提高两到三倍。

在压测时HRegionServer的Handler很多情况下都被卡在reclaimMemStoreMemory()

ps:这个方法在region数目过多时淘宝庄庄说过这个问题,会影响put速度。

因为他每次都会调这一段代码,当有几千上万个region时。。。。。每次put都检查自然有问题,不过这个相对于后面的事情是小问题了,先放这。

public long getGlobalMemStoreSize() {long total = 0;for (HRegion region : onlineRegions.values()) {total += region.memstoreSize.get();}return total;}

下面这段展示了这个方法。

public synchronized void reclaimMemStoreMemory() {if (isAboveHighWaterMark()) {lock.lock();try {while (isAboveHighWaterMark() && !server.isStopped()) {wakeupFlushThread();try {// we should be able to wait forever, but we've seen a bug where// we miss a notify, so put a 5 second bound on it at least.flushOccurred.await(5, TimeUnit.SECONDS);} catch (InterruptedException ie) {Thread.currentThread().interrupt();}}} finally {lock.unlock();}} else if (isAboveLowWaterMark()) {wakeupFlushThread();}}

其中flushOccurred.await(5, TimeUnit.SECONDS);这一部分将所有写入线程都block了,但这也不完全怪flush做得慢,我们实际压测时,flush还是很快的,只是compact不及时,flush就会被阻塞。

参这篇jira的内容

https://issues.apache.org/jira/browse/HBASE-2646

https://issues.apache.org/jira/browse/HBASE-2981

https://issues.apache.org/jira/browse/HBASE-2832

run YCSB写入压测时,HBase有明显的停顿,写入性能有跳变。在EMC一篇关于hypertable和HBase的测试中,提到HBase的性能被GC所累,我觉得他们有可能错误地把

flush和compaction中的停顿当作JAVA gc了。因为在给RegionServer分配24GB内存时,GC的时间很短(毫秒级)。

第一步:为flush添加线程池

HBase flush memorystore时是由一个线程顺序将数据

hbase.hstore.blockingStoreFiles ()同时flush时会获取Region writeLock的writeLock().来做snapshot,而所有的修改包括mult,put,delete都要获取readlock,

所以写入操作与flush大部分代码都只能串行执行,并不能像流水号线一样边写入边flush。所以压测时就会一顿一顿的。

当然这是其中一个原因,我们先来解决这个原因,将flush变成多线程并行flush再来探讨另一个导致flush无法并行执行的原因。

https://issues.apache.org/jira/browse/HBASE-2832

于是我仿照Jonathan的patch在90.4上实现了muti thread memstore flush,Jonathan的实现目前用于trunk,且只针对上面我提到的原因做了改进。

实际测试时并不能达到并行flush的效果。

这一段的主要修改是在MemStoreFlusher 中添加了如下代码,同时每处flush都调用performFlush(HRegion)。

FlushRegionHandler的代码比较多,详细见patch,我会贴到git上https://github.com/ICT-Ope,也可以到微博上@我。

  ExecutorService executor;public void performFlush(HRegion r) {executor.submit(new FlushRegionHandler(this.server, r,this));}

第二步:修改HLog 获取sequenceId时的锁类型

这样做之后,遇到阻碍并行flush的第二个问题,HLog。但测试时发现一次flush的region并没有增加,依然没有效果。

我怀疑HLog中每次flush部分的检查可能还是限制了并发。并在regionserver.wal.HLog.startCacheFlush()中的一段代码找出了问题。
PS:即使用户在每次put时设定不写HLog,HLog也是要在每次flush之后检查有效log的位置,并roll log等操作也不会因此关闭。(测试中每次put时设定不写HLog)

在regionserver.wal.HLog中有如下代码:

  /*** By acquiring a log sequence ID, we can allow log messages to continue while* we flush the cache.** Acquire a lock so that we do not roll the log between the start and* completion of a cache-flush. Otherwise the log-seq-id for the flush will* not appear in the correct logfile.** @return sequence ID to pass {@link #completeCacheFlush(byte[], byte[], long, boolean)}* (byte[], byte[], long)}* @see #completeCacheFlush(byte[], byte[], long, boolean)* @see #abortCacheFlush()*/public long startCacheFlush() {this.cacheFlushLock.lock();return obtainSeqNum();}

这部分被HRegion的internalFlushcache调用,用以得到当前HLog的sequenceId,不得不说这个lock加得太大了,一个RegionServer共用一个HLog啊。。。

此处无非是得到log sequence 然后在store internalFlushcache时写到文件里,hlog roll时从而得知哪段已经写到磁盘了。

所以此处的cacheFlushLock 应当改为ReentrantReadWriteLock,并在此处只加readLock。rolllog时加writeLog。

   this.updatesLock.writeLock().lock();//此处已经将本Region所有修改操作lock了。final long currentMemStoreSize = this.memstoreSize.get();List<StoreFlusher> storeFlushers = new ArrayList<StoreFlusher>(stores.size());boolean compactionRequested = false;
try {
sequenceId = (wal == null)? myseqid: wal.startCacheFlush();//在这,上面那个方法又加了个RegionServer级的锁,且还不是RW锁。completeSequenceId = this.getCompleteCacheFlushSequenceId(sequenceId);for (Store s : stores.values()) {storeFlushers.add(s.getStoreFlusher(completeSequenceId));}// prepare flush (take a snapshot)for (StoreFlusher flusher : storeFlushers) {flusher.prepare();}

做以上修改之后HBase多线程flush没有问题了。下面是第三步:

第三步:为compact添加线程池,顺便注释掉split部分。

不过随之而来的另外一个问题就是当flush频繁之后系统吞吐量显著提高,但生成的小文件数量变多,compaction的负担就大了。

由于下面这段代码,compact忙不过来时,flush也是会被阻塞的,如此写入也就被阻塞了。

private boolean flushRegion(final FlushRegionEntry fqe) {HRegion region = fqe.region;if (!fqe.region.getRegionInfo().isMetaRegion() &&isTooManyStoreFiles(region)) {if (fqe.isMaximumWait(this.blockingWaitTime)) {LOG.info("Waited " + (System.currentTimeMillis() - fqe.createTime) +"ms on a compaction to clean up 'too many store files'; waited " +"long enough... proceeding with flush of " +region.getRegionNameAsString());} else {

当StoreFile数到7(默认),flush就要等compact把StoreFile压到一个文件里。如此单线程的compact又成为瓶颈阻碍HBase的写入吞吐量了。所以最后又把compact也改成了线程池,同时顺便把split的代码给注释掉了。然后把blockflush的storefile数目从7改到两千,这样写入流水基本顺畅了。最后的效果是HBase压测时cpu一直利用充分。HBase中 multi flush compact的流水线基本并行化了。整个系统的吞吐量大幅度提升。此时当打开gz软件压缩(no native,用native压时,压缩是单线程的)时,系统的cpu利用率才充分一些。

第四步:为HBaseClient添加到RegoinServer的连接池。

但即使如此,cpu也没有用到100%啊,既然是压测那一定要达到某个硬件瓶颈才算压出效果吧。此时突然意识到HBaseClient端的一个问题:所有线程共用一个socket连接与RS交换数据,so果端修改了HBaseClient的代码使用了连接池。(线上系统如非某应用独占,最好不要改这个地方)。改完之后用70个线程压测时总算达到了我要的效果,RS 16核2.4GHz的CPU满载(no compression,multi-thread flush and compact)。更详细的测试报告我将会在后续的博文中放出,测试的效果大概是写入吞吐量有两到三倍提升。

HBase写入性能分析及改造—multi-thread flush and compaction(约能提高两到三倍吞吐量,带压缩测试)相关推荐

  1. 【高级内部资料】.NET数据批量写入性能分析 第一篇

    [高级内部资料].NET数据批量写入性能分析 第一篇 说起数据的批量写入,相信大家应该不陌生了,那么我们本系列的文章不准备讲述如何来进行数据的批量写入,而是介绍常用的数据批量写入方法的性能分析. 同时 ...

  2. mysql并发写入性能分析

    目前,在很多OLTP场景中,MySQL数据库都有着广泛的应用,也有很多不同的使用方式.从数据库的业务需求.架构设计.运营维护.再到扩容迁移,不同的MySQL架构有不同的特点,适应一定的业务场景,或者解 ...

  3. HashMap 的 7 种遍历方式与性能分析!「修正篇」

    这是我的第 57 篇原创文章 首先,给大家说声抱歉~ 事情经过是这样子的,五一节前我发布了一篇文章<HashMap 的 7 种遍历方式与性能分析!>,但是好心的网友却发现了一个问题,他说 ...

  4. HBase写性能优化策略

    HBase写入通常会遇到两种问题: # 写的性能很差 # 根本写不进去 一 HBase写入性能优化 1.1 是否需要写WAL? WAL是否需要同步写? WAL机制可以确保数据即使写入缓存的数据丢失了, ...

  5. Linux性能分析工具top命令详解

    top命令是linux下常用的性能分析工具,能够实时的显示系统中各个进程的资源占用情况,常用于服务端性能分析. top命令说明: top命令的结果分为两部分: 统计信息:前五行是系统的整体统计信息. ...

  6. 【转】一文掌握 Linux 性能分析之网络篇(续)

    [转]一文掌握 Linux 性能分析之网络篇(续) 在上篇网络篇中,我们已经介绍了几个 Linux 网络方向的性能分析工具,本文再补充几个.总结下来,余下的工具包括但不限于以下几个: sar:统计信息 ...

  7. 一文掌握 Linux 性能分析之网络篇(续)

    在上篇网络篇中,我们已经介绍了几个 Linux 网络方向的性能分析工具,本文再补充几个.总结下来,余下的工具包括但不限于以下几个: sar:统计信息历史 traceroute:测试网络路由 dtrac ...

  8. 系统级性能分析工具perf的介绍与使用

    测试环境:Ubuntu16.04 + Kernel:4.4.0-31 apt-get install linux-source cd /usr/src/tools/perf make &&am ...

  9. linux 系统级性能分析工具 perf 的介绍与使用

    目录 1. 背景知识 1.1 tracepoints 1.2 硬件特性之cache 2. 主要关注点 3. perf的使用 3.0 perf引入的overhead 3.1 perf list 3.2 ...

最新文章

  1. eclipse 3.55安装j2ee开发工具
  2. C++ Boost库初步使用 - 使用CFree
  3. Use BAdI - call_workitem_exit workflow
  4. 以后可能用到的一些OQL
  5. 搜狗输入法Android5.1,ESXI 服务器断电之后一直 LOADING MODULE IPMI_SI_DRV 的解决办法...
  6. 谷歌不支持调用摄像头麦克风_谷歌突然推出Android 11开发者预览版 新版带来部分新功能和改进...
  7. 2014届去哪儿校园招聘笔试题
  8. mysql:分组中某字段最大值的查询结果
  9. java核心技术卷1 所有示例代码
  10. Keil5安装教程(包含C51与MDK共存)WIN10 亲测可用
  11. linux当前文件下的文件数,Linux下统计当前文件夹下的文件个数、目录个数(转)...
  12. 读书笔记:100岁前的健康指南
  13. 企业微信自建应用获取用户信息
  14. 暑假的计划【写在这里,监督自己】
  15. 数仓治理:数据地图长什么样?
  16. jquery vue 替代_vue能代替jquery吗
  17. DANet(双重注意力融合网络)
  18. TUPE :重新思考语言预训练中的位置编码
  19. java+opencv+selenium实现滑块滑动破解
  20. BlackNurse新型DoS攻击 15M流量就可以打瘫思科防火墙 思科做出了回应

热门文章

  1. 计算机组装 项目教学,计算机组装与维护项目教学课程.doc
  2. 收发一体超声波测距离传感器模块_超声波一体化液位计
  3. 我讨厌慢节奏工作,我喜欢充实生活
  4. 一个关于卷积神经网络应用于图像语义分割的PPT
  5. 计算机专业考研苏大还是西工大好,苏州有4所985,1所211大学,苏州和深圳,哪家厉害?...
  6. 一级计算机ppt操作常考知识点,2017职称计算机考试PowerPoint知识点:PPT的操作界面...
  7. 四则运算出题java_四则运算自动出题之javaweb版
  8. idea下载其它版本方法
  9. 基于Python+SQLite实现校园信息化统计平台【100010095】
  10. python淘宝爬虫_淘宝直播python爬虫