HBase如何合理设置客户端Write Buffer - 大圆那些事 - 博客园

标签: | 发表时间:2020-02-09 19:11 | 作者:
出处:https://www.cnblogs.com

作者: 大圆那些事| 转载请以超链接形式标明文章原始出处和作者信息
网址: http://www.cnblogs.com/panfeng412/archive/2012/10/16/how-to-use-hbase-client-write-buffer.html

HBase客户端API提供了Write Buffer的方式,即批量提交一批Put对象到HBase服务端。本文将结合HBase相关源码,对其进行深入介绍,分析如何在实际项目中合理设置和使用它。

1. 什么时候需要Write Buffer?

默认情况下,一次Put操作即要与Region Server执行一次RPC操作,其执行过程可以被拆分为以下三个部分:

  • T1:RTT(Round-Trip Time),即网络往返时延,它指从客户端发送数据开始,到客户端收到来自服务端的确认,总共经历的时延,不包括数据传输的时间;
  • T2:数据传输时间,即Put所操作的数据在客户端与服务端之间传输所消耗的时间开销,当数据量大的时候,T2的时间开销不容忽略;
  • T3:服务端处理时间,对于Put操作,即写入WAL日志(如果设置了WAL标识为true)、更新MemStore等。

其中,T2和T3都是不可避免的时间开销,那么能不能减少T1呢?假设我们将多次Put操作打包起来一次性提交到服务端,则可以将T1部分的总时间从T1 * N降低为T1,其中T1指的是单次RTT时间,N为Put的记录条数。

正是出于上述考虑,HBase为用户提供了客户端缓存批量提交的方式(即Write Buffer)。假设RTT的时间较长,如1ms,则该种方式能够显著提高整个集群的写入性能。

那么,什么场景下适用于该种模式呢?下面简单分析一下:

  • 如果Put提交的是小数据(如KB级别甚至更小)记录,那么T2很小,因此,通过该种模式减少T1的开销,能够明显提高写入性能。
  • 如果Put提交的是大数据(如MB级别)记录,那么T2可能已经远大于T1,此时T1与T2相比可以被忽略,因此,使用该种模式并不能得到很好的性能提升,不建议通过增大Write Buffer大小来使用该种模式。

2. 如何配置使用Write Buffer?

如果要启动Write Buffer模式,则调用HTable的以下API将auto flush设置为false:

voidsetAutoFlush(booleanautoFlush)

默认配置下,Write Buffer大小为2MB,可以根据应用实际情况,通过以下任意方式进行自定义:

1) 调用HTable接口设置,仅对该HTable对象起作用:

voidsetWriteBufferSize(longwriteBufferSize)throwsIOException

2) 在hbase-site.xml中配置,所有HTable都生效(下面设置为5MB):

<property>
<name>hbase.client.write.buffer</name>
<value>5242880</value>
</property>

该种模式下向服务端提交的时机分为显式和隐式两种情况:

1) 显式提交:用户调用flushCommits()进行提交;

2) 隐式提交:当Write Buffer满了,客户端会自动执行提交;或者调用了HTable的close()方法时无条件执行提交操作。

3. 如何确定每次flushCommits()时实际的RPC次数?

客户端提交后,所有的Put操作可能涉及不同的行,然后客户端负责将这些Put对象根据row key按照region server分组,再按region server打包后提交到region server,每个region server做一次RPC请求。如下图所示:

 

 

4. 如何确定每次flushCommits()时提交的记录条数?

下面我们先从HBase存储原理层面“粗略”分析下HBase中的一条Put记录格式:

HBase中Put对象的大小主要由若干个KeyValue对的大小决定(Put继承自org/apache/hadoop/hbase/client/Mutation.java,具体见Mutation的代码所示),而KeyValue类中自带的字段占用约50~60 bytes(参考源码:org/apache/hadoop/hbase/KeyValue.java),那么客户端Put一行数据时,假设column qualifier个数为N,row key长度为L1 bytes,value总长度为L2 bytes,则该Put对象占用大小可按以下公式预估:

Put Size = ((50~60) + L1) * N + L2) bytes

下面我们通过对HBase的源码分析来进一步验证以上理论估算值:

HBase客户端执行put操作后,会调用put.heapSize()累加当前客户端buffer中的数据,满足以下条件则调用flushCommits()将客户端数据提交到服务端:

1)每次put方法调用时可能传入的是一个List<Put>,此时每隔DOPUT_WB_CHECK条(默认为10条),检查当前缓存数据是否超过writeBufferSize,超过则强制执行刷新;

2)autoFlush被设置为true,此次put方法调用后执行一次刷新;

3)autoFlush被设置为false,但当前缓存数据已超过设定的writeBufferSize,则执行刷新。

privatevoiddoPut(finalList<Put> puts)throwsIOException {intn = 0;for(Put put : puts) {
            validatePut(put);
            writeBuffer.add(put);
            currentWriteBufferSize+=put.heapSize();//we need to periodically see if the writebuffer is full instead//of waiting until the end of the Listn++;if(n % DOPUT_WB_CHECK == 0
                    && currentWriteBufferSize >writeBufferSize) {
                flushCommits();
            }
        }if(autoFlush || currentWriteBufferSize >writeBufferSize) {
            flushCommits();
        }
    }

由上述代码可见,通过put.heapSize()累加客户端的缓存数据,作为判断的依据;那么,我们可以编写一个简单的程序生成Put对象,调用其heapSize()方法,就能得到一行数据实际占用的客户端缓存大小(该程序需要传递上述三个变量:N,L1,L2作为参数):

importorg.apache.hadoop.hbase.client.Put;importorg.apache.hadoop.hbase.util.Bytes;publicclassPutHeapSize {/***@paramargs*/publicstaticvoidmain(String[] args) {if(args.length != 3) {
            System.out.println("Invalid number of parameters: 3 parameters!");
            System.exit(1);
        }intN = Integer.parseInt(args[0]);intL1 = Integer.parseInt(args[1]);intL2 = Integer.parseInt(args[2]);byte[] rowKey =newbyte[L1];byte[] value =null;
        Put put=newPut(rowKey);for(inti = 0; i < N; i++) {
            put.add(Bytes.toBytes("cf"), Bytes.toBytes("c" +i), value);
        }
        System.out.println("Put Size: " + (put.heapSize() + L2) + " bytes");
    }
}

该程序可以用来预估当前设置的write buffer可以一次性批量提交的记录数:

Puts Per Commit = Write Buffer Size / Put Size

更进一步地,如果知道业务中的每秒产生的数据量,就可知道客户端大概多长时间会隐式调用flushCommits()向服务端提交一次;同时也可反过来根据数据实时刷新频率调整Write Buffer大小。

5. Write Buffer有什么潜在的问题?

首先,Write Buffer存在于客户端的本地内存中,那么当客户端运行出现问题时,会导致在Write Buffer中未提交的数据丢失;由于HBase服务端还未收到这些数据,因此也无法通过WAL日志等方式进行数据恢复。

其次,Write Buffer方式本身会占用客户端和HBase服务端的内存开销,具体见下节的详细分析。

6. 如何预估Write Buffer占用的内存?

客户端通过Write Buffer方式提交的话,会导致客户端和服务端均有一定的额外内存开销,Write Buffer Size越大,则占用的内存越大。客户端占用的内存开销可以粗略使用以下公式预估:

hbase.client.write.buffer * number of HTableobjectforwriting

而对于服务端来说,可以使用以下公式预估占用的Region Server总内存开销:

hbase.client.write.buffer * hbase.regionserver.handler.count * number of region server

其中,hbase.regionserver.handler.count为每个Region Server上配置的RPC Handler线程数。

 

相关 [hbase 客户端 write] 推荐:

HBase如何合理设置客户端Write Buffer - 大圆那些事 - 博客园

- -
大圆那些事| 转载请以超链接形式标明文章原始出处和作者信息. HBase客户端API提供了Write Buffer的方式,即批量提交一批Put对象到HBase服务端. 本文将结合HBase相关源码,对其进行深入介绍,分析如何在实际项目中合理设置和使用它. 什么时候需要Write Buffer. 默认情况下,一次Put操作即要与Region Server执行一次RPC操作,其执行过程可以被拆分为以下三个部分:.

HBase入门 客户端操作

- - 学着站在巨人的肩膀上
HBase入门HBase入门. 部分内容参考于http://www.nabble.com/Re%3A-Map-Reduce-over-HBase---sample-code-p18253120.html. 对于HBase使用的类似与BigTable的技术我们这里就不仔细描述,可以参考google的论文以及网上的一些相关资料.另外,HBase的配置在HBase的官方文档中有很详细的描述.可以参见相关文档.

Write-ahead logging(WAL)

- - 掘金 后端
WAL( Write-ahead logging预写日志)是数据库用于实现事务原子性和持久性的技术. 所有的修改在提交之前,系统将其先可靠的写入到 WAL 管理的 Log 文件中,再通过 Log 文件中记录的日志执行真正的操作. 如果遵循这种过程,则无需在每个事务的提交时 等待系统落盘,因为无论何时何种情况,都可以使用日志进行数据库的恢复.

Windows7+Eclipse环境下Hbase Java客户端的开发

- - zzm
Centos 下Hbase0.98.10-hadoop2 集群的配置. 在Eclipse中创建Maven的工程. 将集群的hbase-site.xml文件放到工程的classes目录下. C:\windows\system32\drivers\etc文件,将Hbase集群的IP以及域名配置到该文件中.

HBase客户端访问超时原因及参数优化_Fang的博客-CSDN博客

- -
默认的HBase客户端的参数配置是没有做过优化的,所以对于低延时响应的HBase集群,需要对客户端的参数进行优化. 以毫秒计算的所有HBase RPC超时,默认为60s. 该参数表示一次RPC请求的超时时间. 如果某次RPC时间超过该值,客户端就会主动关闭socket. 如果经常出现java.io.IOException: Connection reset by peer异常问题,估计HBase集群出现了大量高并发读写业务或者服务器端发生了比较严重的Full GC等问题,导致某些请求无法得到及时处理,超过了设置的时间间隔.

Redo write触发的四种情况

- - CSDN博客推荐文章
1、当LGWR空闲的时候,会每隔3秒检查一次是否有从redo buffer写入redelog中的数据,如果有,一个后台进程就会自动的执行将其写入. 2、当有进程要从redo buffer中分配空间时,会先计算redo buffer中已经占用的空间,如果该空间大于_log_io_size这个参数值,并且此时的LGWR处于空闲状态,便会被激活执行后台写.

编程每一天(Write Code Every Day)

- - 博客园_知识库
   英文原文: Write Code Every Day.   去年秋天,我的个人项目似乎走到了尽头:我一直没能取得必要的进展,在不牺牲我的主业( 可汗学院的全职工作) 的情况下,我无法完成更多的个人编程事项.   我个人项目上的工作始终存在着几个严重问题. 我把这些工作主要放在周末,但有时也可能是周末的晚上.

Write or die:不能停笔的写作应用

- tossking - 爱范儿 · Beats of Bits
作家 Alisa Bowman 在文章《如何写得快》中,认为如果要写得快,就“不能停笔”:. 一开始就不要停下,除非你脑中在没有词可以涌出. 不要因为拼写错误而停下,不要因为语法而停下,不要因为反复思量而停下. Write or Die(WoD),就是一个让你“不能停笔”的应用. 如果停下笔来,它就会惩罚你,直到你重新提笔写作为止.

how to write extension for firefox -- 如何给firefox编写插件

- - CSDN博客Web前端推荐文章
1.1 创建一个dev profile. 1.3 创建或者修改一些preference. 1.4 启动firefox. 使用-no-remoet可以使你同时用自己平时使用的profile浏览网页,和你开发的profile互补干扰. Note 1:当你修改install.rdf中有关firefox的compatile version时,有时会提示你版本不兼容当前的firefox,不要理会,.

hbase介绍

- AreYouOK? - 淘宝数据平台与产品部官方博客 tbdata.org
hbase是bigtable的开源山寨版本. 是建立的hdfs之上,提供高可靠性、高性能、列存储、可伸缩、实时读写的数据库系统. 它介于nosql和RDBMS之间,仅能通过主键(row key)和主键的range来检索数据,仅支持单行事务(可通过hive支持来实现多表join等复杂操作). 主要用来存储非结构化和半结构化的松散数据.