HBase 读取性能优化


1. HBase服务端优化

1.1 读请求是否均衡

如果数据吞吐量较大,且一次查询返回的数据量较大,则Rowkey 必须进行散列化处理,同时建表必须进行预分区处理。对于以get为主的查询场景,则将表进行hash预分区,均匀分布;如果以scan为主,则需要兼顾业务场景设计rowkey,在满足查询需求的前提下尽量对数据打散并进行负载均衡。

1.2 BlockCache 设置是否合理

一个通用的规则就是:如果 JVM 内存配置量小于 20G,BlockCache 策略选择 LRUBlockCache;否则选择 BucketCache 策略的 offheap 模式。如果是heap模式,也可以根据业务场景的读写比例来配置堆中读写heap的比例,默认堆中读写缓存均占heap的40%,即读写均衡。

1.3 HFile 文件是否太多

一个 Store 中包含多个 HFile 文件,文件越多,检索所需的 IO 次数越多,读取延迟也越高。文件数量通常取决于 Compaction 的执行策略,一般和两个配置参数有关:hbase.hstore.compactionThreshold 和 hbase.hstore.compaction.max.size ,前者表示一个 store 中的文件数超过阈值就应该进行合并,后者表示参与合并的文件大小最大是多少,超过此大小的文件不能参与合并。

可以查看 RegionServer 级别以及 Region 级别的HFile数量,确认 HFile 文件是否过多。

hbase.hstore.compactionThreshold 设置不能太大,默认为3个。

1.4 Compaction 是否消费系统资源过多

由于配置文件中默认的major compact是定时按表执行,且消耗资源很大,对系统性能影响同样很大,所以对于大 Region 读延迟敏感的业务(100G以上)通常不建议开启自动 Major Compaction,手动低峰期触发;小 Region 或者延迟不敏感的业务可以开启 Major Compaction,但建议限制流量。

1.5 数据本地率是不是很低

尽量避免 Region 无故迁移。对于本地化率较低的节点,可以在业务低峰期执行 major_compact。

2. HBase客户端优化

2.1 scan 缓存是否设置合理

在HBase总RPC次数调整到比较合理的前提下,可以考虑将大 scan 场景下将 scan 缓存从 100 增大到 500 或者 1000,用以减少 RPC 次数。

2.2 get 是否使用批量请求

HBase 分别提供了单条 get 以及批量 get 的 API 接口,使用批量 get 接口可以减少客户端到 RegionServer 之间的 RPC 连接数,提高读取吞吐量。

2.3 请求是否可以显式指定列簇或者列

尽量指定列簇或者列进行精确查询。

2.4 离线批量读取请求是否设置禁止缓存

离线批量读取请求设置禁用缓存,scan.setCacheBlocks(false),此种场景适用于离线的全表扫秒,如mapreduce。此时使用缓存不仅无法提升性能,可能还会适得其反。

3. HBase列簇设计优化

建议在任何业务都应该设置布隆过滤器,通常设置为 row,除非确定业务随机查询类型为 row + column,则设置为 rowcol(适合大量指定column的场景,这种场景下占用的缓存内存以及磁盘的量会增加)。

HBase 写入性能调优


1. HBase 服务器端优化

1.1 Region 是否太少

在表的 Region 数量小于 RegionServer 节点数的场景下,需要将切分部分请求负载高的Region,并迁移到其他 RegionServer 节点上,已达到充分利用服务器资源,负载均衡。

1.2 写入请求是否均衡

检查 RowKey 设计以及预分区策略,保证写入请求均衡。针对get查询为主的表,可以使用hash预分区策略;针对scan为主的表,建议使用分段预分区的策略。

1.3 使用 SSD 存储 WAL

将 WAL 文件写到SSD上,对于写性能会有非常大的提升。

使用该特性配置步骤:

使用 HDFS Archival Storage 机制,配置 HDFS 的部分文件目录为 SSD 介质

hbase-site.xml 添加配置

<property>
    <name>hbase.wal.storage.policy</name>
    <value>ONE_SSD</value>
</property>

hbase.wal.storage.policy 默认为 none,用户可以指定 ONESSD(WAL 一个副本写入 SSD 介质)或者 ALLSSD(WAL的三个副本全部写入 SSD 介质)。

2. HBase客户端优化

2.1 是否可以使用 Bulkload 方案写入

Bulkload 是一个 MapReduce 程序,输出 HFile 文件。这种方式的业务场景是离线导入数据,有点事吞吐量大 ,效率高;缺点是实时性差。

2.2 是否需要写WAL?WAL是否需要同步写入

此处划重点:如果业务上能够忍受小分部数据丢失,且需要极限提高写入速度,可以考虑禁用WAL,这样做的缺点就是系统crash的时候会丢一部分数据,且无法做跨集群的replication。

数据写入流程可以理解为 一次顺序写WAL+一次写缓存。

WAL 的持久化分为四个等级:

SKIP_WAL
ASYNC_WAL
SYNC_WAL
FSYNC_WAL

默认为 SYNC_WAL 等级持久化数据。

根据业务关注点在 WAL 机制和写入吞吐量之间作出选择,用户可以通过客户端设置 WAL 持久化策略。

2.3 Put 是否可以同步批量提交

类似 Get 接口。

2.4 Put 是否可以异步批量提交

开启异步批量提交,用户可以设置 setAutoFlush(false),客户端缓存达到阈值(默认2M)后批量提交给 RegionServer。这样做的好处是能够减少RPC调用的次数,提高吞吐量;缺点是如果客户端异常,缓存数据可能丢失。

2.5 写入 KeyValue 数据是否太大

KeyValue 大小对写入性能影响巨大。如果太大,会对性能产生很大的影响。

RowKey的最大长度限制为64KB,但在实际应用中最多不会超过100B。这是由于HBase的rowkey会被多次冗余存储,RowKey越大,浪费的内存和硬盘资源也会越多。

Value过大也会对性能产生很大的影响,也会影响到HBase的响应速度。如果Value过大,建议拆成多列存储,每次返回需要的值,或者将Value存储到HDFS上,在HBase中存储url