开发者学堂课程【HBase 入门教程:HBase 优化_3】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/397/detail/5095
HBase 优化_3
内容介绍
一、写表操作
二、读表操作
三、HTable
四、HTablePool
五、Hbase 和 DBMS 比较
一、写表操作
1. HTable 参数设置
(1) Auto Flush
通过调用 HTable.setAutoFlush(false) 方法可以将 HTable 写客户端的自动 flush 关闭,这样可以批量写入数据到 HBase ,而不是有一条 put 就执行一次更新,只有当 put 填满客户端写缓存时,才实际向 HBase 服务端发起写请求。默认情况下 auto flush 是开启的。
(2) Write Buffer
通过调用 HTable.setWriteBufferSize(writeBufferSize) 方法可以设置 HTable 客户端的写 buffer 大小,如果新设置的 buffer 小于当前写 buffer 中的数据时, buffer 将会被 flush 到服务端。其中, writeBufferSize 的单位是 byte 字节数,可以根据实际写入数据量的多少来设置该值。
(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 日志进行恢复。
二、读表操作
1. 多 HTable 并发读
创建多个 HTable 客户端用于读操作,提高读数据的吞吐量,一个例子:
static final Configuration conf =HBaseConfiguration.create();
static final String table_log_name = “user_log”;
rTableLog = new HTable[tableN];
for (int i = 0; i < tableN; i++) {
rTableLog[i] = new HTable(conf, table_log_name);
rTableLog[i].setScannerCaching(50);
}
2. HTable 参数设置
(1) Scanner Caching
hbase.client.scanner.caching 配置项可以设置 HBase scanner 一次从服务端抓取的数据条数,默认情况下一次一条。通过将其设置成一个合理的值,可以减少 scan 过程中 next() 的时间开销,代价是 scanner 需要通过客户端的内存来维持这些被 cache 的行记录。
有三个地方可以进行配置:
①在 HBase 的 conf 配置文件中进行配置;
②通过调用 HTable.setScannerCaching(int scannerCaching) 进行配置;
③通过调用 Scan.setCaching(int caching) 进行配置。三者的优先级越来越高。
(2) Scan Attribute Selection
scan 时指定需要的 Column Family ,可以减少网络传输数据量,否则默认 scan 操作会返回整行所有 Column Family 的数据。
(3) Close ResultScanner
通过 scan 取完数据后,记得要关闭 ResultScanner ,否则 RegionServer 可能会出现问题(对应的 Server 资源无法释放)。
3.Blockcache
HBase上 Regionserver 的内存分为两个部分,一部分作为 Memstore,主要用来写;另外一部分作为 BlockCache,主要用于读。
写请求会先写入 Memstore ,Regionserver 会给每个 region 提供一个 Memstore ,当 Memstore 满64MB以后,会启动 flush 刷新到磁盘。当 Memstore 的总大小超过限制时(heapsize * hbase.regionserver.global.memstore.upperLimit * 0.9),会强行启动 flush 进程,从最大的 Memstore 开始 flush 直到低于限制。
读请求先到 Memstore 中查数据,查不到就到 BlockCache 中查,再查不到就会到磁盘上读,并把读的结果放入 BlockCache。由于 BlockCache 采用的是 LRU 策略,因此 BlockCache 达到上限(heapsize * hfile.block.cache.size * 0.85)后,会启动淘汰机制,淘汰掉最老的一批数据。
一个 Regionserver 上有一个 BlockCache 和 N 个 Memstore ,它们的大小之和不能大于等于 heapsize * 0.8,否则HBase 不能启动。默认 BlockCache 为0.2,而 Memstore 为0.4。对于注重读响应时间的系统,可以将 BlockCache 设大些,比如设置 BlockCache=0.4 ,Memstore=0.39,以加大缓存的命中率。
三、HTable
HTable是 HBase 客户端与 HBase 服务端通讯的 Java API 对象,客户端可以通过 HTable 对象与服务端进行 CRUD 操作(增删改查)。它的创建很简单:
Configuration conf = HBaseConfiguration.create();
HTable table = new HTable(conf, "tablename");
//TODO CRUD Operation……
HTable 使用时的一些注意事项:
1、规避 HTable 对象的创建开销
因为客户端创建 HTable 对象后,需要进行一系列的操作:检查.META.表确认指定名称的 HBase 表是否存在,表是否有效等等,整个时间开销比较重,可能会耗时几秒钟之长,因此最好在程序启动时一次性创建完成需要的 HTable 对象,如果使用 Java API ,一般来说是在构造函数中进行创建,程序启动后直接重用。
2、HTable 对象不是线程安全的
HTable 对象对于客户端读写数据来说不是线程安全的,因此多线程时,要为每个线程单独创建复用一个 HTable 对象,不同对象间不要共享 HTable 对象使用,特别是在客户端 auto flash 被置为 false 时,由于存在本地 write buffer ,可能导致数据不一致。
3、HTable 对象之间共享 Configuration
四、HTablePool
HTablePool可以解决 HTable 存在的线程不安全问题,同时通过维护固定数量的HTable对象,能够在程序运行期间复用这些 HTable 资源对象。
Configuration conf = HBaseConfiguration.create();
HTablePool pool = new HTablePool(conf, 10);
1. HTablePool 可以自动创建 HTable 对象,而且对客户端来说使用上是完全透明的,可以避免多线程间数据并发修改问题。
2. HTablePool 中的 HTable 对象之间是公用 Configuration 连接的,能够可以减少网络开销。
HTablePool 的使用很简单:每次进行操作前,通过 HTablePool 的 getTable 方法取得一个 HTable 对象,然后进行put/get/scan/delete 等操作,最后通过 HTablePool 的 putTable 方法将 HTable 对象放回到 HTablePool 中。
五、Hbase 和 DBMS比较
查询数据不灵活:
不能使用 column 之间过滤查询
不支持全文索引。使用 solr 和 hbase 整合完成全文搜索。
a) 使用 MR 批量读取 hbase 中的数据,在 solr 里面建立索 引(nostore)之保存 rowkey 的值
b) 根据关键词从索引中搜索到 rowkey (分页)
c) 根据 rowkey 从 hbase 查询所有数据