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:
void setAutoFlush(boolean autoFlush)
默认配置下,Write Buffer大小为2MB,可以根据应用实际情况,通过以下任意方式进行自定义:
1)调用HTable接口设置,仅对该HTable对象起作用:
void setWriteBufferSize(long writeBufferSize) throws IOException
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请求。如下图所示:
更多精彩内容:http://www.bianceng.cnhttp://www.bianceng.cn/database/extra/