转载自:https://blog.youkuaiyun.com/hljlzc2007/article/details/11744221
https://blog.youkuaiyun.com/huoyunshen88/article/details/19559243
https://blog.youkuaiyun.com/xiaolang85/article/details/8025991
2. 写表操作
2.1 多HTable并发写
创建多个HTable客户端用于写操作,提高写数据的吞吐量,一个例子:
static final Configuration conf = HBaseConfiguration.create();
static final String table_log_name = “user_log”;
wTableLog = new HTable[tableN];
for (int i = 0; i < tableN; i++) {
wTableLog[i] = new HTable(conf, table_log_name);
wTableLog[i].setWriteBufferSize(5 * 1024 * 1024); //5MB
wTableLog[i].setAutoFlush(false);
}
2.2 HTable参数设置
2.2.1 Auto Flush
通过调用HTable.setAutoFlush(false)方法可以将HTable写客户端的自动flush关闭,这样可以批量写入数据到HBase,而不是有一条put就执行一次更新,只有写入的数据超过配置的writeBufferSize(通过hbase.client.write.buffer配置,默认为2M)时才提交写数据请求,如果最后的写入数据没有超过2M,则在调用close方法时会进行最后的提交。默认情
2.2.2 Write Buffer
通过调用HTable.setWriteBufferSize(writeBufferSize)方法可以设置HTable客户端的写buffer大小(必须先要HTable.setAutoFlush(false)),如果新设置的buffer小于当前写buffer中的数据时,buffer将会被flush到服务端。其中,writeBufferSize的单位是byte字节数,可以根据实际写入数据量的多少来设置该值。
注意,这样做的好处在于可以减少RPC连接次数。同时,也得考虑一下服务端因此而消耗的内存:hbase.client.write.buffer * hbase.regionserver.handler.count。需要在减少PRC次数和增加服务器端内存之间找到平衡点。
2.2.3 WAL Flag
在HBae中,客户端向集群中的RegionServer提交数据时(Put/Delete操作),首先会先写WAL(Write Ahead Log)日志(即HLog,一个RegionServer上的所有Region共享一个HLog),只有当WAL日志写成功后,再接着写MemStore,然后客户端被通知提交数据成功;如果写WAL日志失败,客户端则被通知提交失败。这样做的好处是可以做到RegionServer宕机后的数据恢复。
因此,对于相对不太重要的数据,可以在Put/Delete操作时,通过调用Put.setWriteToWAL(false)或Delete.setWriteToWAL(false)函数,放弃写WAL日志,从而提高数据写入的性能。
值得注意的是:谨慎选择关闭WAL日志,因为这样的话,一旦RegionServer宕机,Put/Delete的数据将会无法根据WAL日志进行恢复。
2.3 批量写
通过调用HTable.put(Put)方法可以将一个指定的row key记录写入HBase,同样HBase提供了另一个方法:通过调用HTable.put(List<Put>)方法可以将指定的row key列表,批量写入多行记录,这样做的好处是批量执行,只需要一次网络I/O开销,这对于对数据实时性要求高,网络传输RTT高的情景下可能带来明显的性能提升。
2.4 多线程并发写
在客户端开启多个HTable写线程,每个写线程负责一个HTable对象的flush操作,这样结合定时flush和写buffer(writeBufferSize),可以既保证在数据量小的时候,数据可以在较短时间内被flush(如1秒内),同时又保证在数据量大的时候,写buffer一满就及时进行flush。下面给个具体的例子:
for (int i = 0; i < threadN; i++) {
Thread th = new Thread() {
public void run() {
while (true) {
try {
sleep(1000); //1 second
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (wTableLog[i]) {
try {
wTableLog[i].flushCommits();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
};
th.setDaemon(true);
th.start();
}
RPC Handler
修改hbase-site.xml的hbase.regionserver.handler.count配置项:
<property>
<name>hbase.regionserver.handler.count</name>
<value>100</value>
</property>
该配置定义了每个Region Server上的RPC Handler的数量。Region Server通过RPC Handler接收外部请求并加以处理。所以提升RPC Handler的数量可以一定程度上提高HBase接收请求的能力。当然,handler数量也不是越大越好,这要取决于节点的硬件情况。
Compression 压缩
HColumnDescriptor hcd = new HColumnDescriptor(familyName);
hcd.setCompressionType(Algorithm.SNAPPY);
数据量大,边压边写也会提升性能的,毕竟IO是大数据的最严重的瓶颈,哪怕使用了SSD也是一样。众多的压缩方式中,推荐使用SNAPPY。从压缩率和压缩速度来看,性价比最高。
Replication
虽然推荐replica=3,不过当数据量很夸张的时候,一般会把replica降低到2。当然也不推荐随便降低replica。
Compaction
在插数据时,打开HMaster的web界面,查看每个region server的request数量。确保大部分时间,写请求在region server层面大致平均分布。
在此前提下,我们再考虑compaction的问题。继续观察request数量,你会发现在某个时间段,若干region server接收的请求数为0(当然这也可能是client根本没有向这个region server写数据,所以之前说,要确保请求在各region server大致平均分布)。这很有可能是region server在做compaction导致。compaction的过程会block写。
优化的思路有两种,一是提高compaction的效率,二是减少compaction发生的频率。
提高以下两个属性的值,以增加执行compaction的线程数:
hbase.regionserver.thread.compaction.large
hbase.regionserver.thread.compaction.small
减少Region Split次数
region split是提升写性能的一大障碍。减少region split次数可以从两方面入手,一是预分配region。其二是适当提升hbase.hregion.max.filesize
提升region的file容量也可以减少split的次数。具体的值需要按照你的数据量,region数量,row key分布等情况具体考量。一般来说,3~4G是不错的选择。
HFile format version
0.92.0后的version都应该是2。v2比v1支持更大的region大小。一般经验是Region越大越少,性能更好(当然也不能过分大,否则major compaction的时候时间长的吃不消)。所以推荐把hfile.format.version改成2,并提高hfile大小。对于使用v1 format的用户,不用担心,数据迁移到v2上是有工具的。具体参见HBASE-1621。
hbase.ipc.client.tcpnodelay
设置成True。关闭Nagle,可能提高latency。当然HDFS也关掉TPC Nagle。
1225

被折叠的 条评论
为什么被折叠?



