Hbase写入性能优化
背景
HBase是一个nosql数据库,既然是数据库,就会涉及到增删改查,而且hbase一般是海量数据场景下使用,使用的不好就会出现性能问题,这里我将自己总结的一些经验分享给大家,仅供参考。
1.数据格式
io是影响性能的主要方面,数据要经过client提交给server端,然后再持久化到磁盘,数据本身越小性能越高。
hbase可以通过rowkey快速查询,也可以通过filter进行过滤搜索(不建议使用,性能很差),其他不需要查询的数据可以尽可能的减小,比如将其他数据进行压缩(同时需考虑解压缩的性能开销),一般我们用protobuf进行编码后再进行存储(编码后会不方便查看,但比存json性能高,反序列化性能也比json好);另外,在定义cloumn时,也尽可能短,不要使用超长字符串定义属性。
2.启用表压缩
启用表压缩可以很大程度节约磁盘,一般采用LZO或者snappy进行压缩,如果是json数据,压缩效率可以达到90%。
3.启用分表策略
超大表在使用时会存在诸多不便,region非常多,不按rowkey的数据访问性能极差,一些数据导出功能基本不可用,数据迁移要命等都是致命问题。
hbase不像elasticsearch天生就支持分表,因此需要自己定义分表策略,可以根据数据的规模和使用途径,按业务类型或者年,月,日等进行分表,分表会带来几个问题:
(1)无法知道某个用户(假设存的是用户数据)是否产生过数据,因为分布在很多表里,这个时候如果要查询数据,需要定义查询范围,比如最近一个月或者6个月。
(2)如果想查询某个用户最后一次上报数据,需要通过视图,快照的方式弥补。
(3)由于分表之后会不断创建新表,需要注意写热点问题。
但分表的好处也不少:
(1)方便做数据老化,可以按天或者按月做数据删除或者归档到磁带。
(2)分表之后,新表的region相对要少的多,数据量也少的多,再做数据扫描时效率要高。
(3)数据迁移和备份的效率要高,可以对单个表做迁移和备份。
4.启用建表预分区
hbase建表是默认只有一个region,也就是说所有的数据都会往一个region里面写,当然可以通过region拆分策略分成多个region,但具体多少region才会匹配当前服务器的能力?再加上如果启用了分表策略,每次新建表的时候都会出现写热点,这个时候会是致命的。
region预分区就是提前创建多个region,每个region有startkey和endkey,不同的数据根据自己生成的rowkey会落入不同的region。具体分多少个region,可以根据集群的数量,数据的并发等来决定,预分的region数不代表将来总的region数,在预分的region达到region拆分的策略后还会进行自动拆分。
5.多线程写入
多线程写入,一是可以充分利用client端物理资源,避免客户端的逻辑处理,导致写入性能卡在客户端;二是可以快速写满buffer,快速的刷写磁盘,一般我们采用线程池进行写操作,但同时要注意线程队列的控制,避免OOM,对于客户端的内存容量,也需要适当调高一些。
6.批量异步提交
hbase1.x之后,有新的api支持异步提交,通过BufferedMutator API,每次提交List
7.hbase日志文件写入(WAL)
WAL又可以理解HLOG操作,是保证数据可靠性的重要举措,HLOG存储在hdfs上,当出现宕机或者regionserver挂掉等场景,数据可以从hlog恢复。
WAL分异步和同步,也可以关闭,hbase默认是同步写hlog,为了提升性能,我们可以改为异步写hlog或者不写hlog(需要评估数据的重要性,短暂的少量数据丢失是否可以容忍),WAL有以下几种策略。
SKIP_WAL:只写缓存,不写HLog日志。这种方式因为只写内存,因此可以极大的提升写入性能,但是数据有丢失的风险。在实际应用过程中并不建议设置此等级,除非确认不要求数据的可靠性。
ASYNC_WAL:异步将数据写入HLog日志中。
SYNC_WAL:同步将数据写入日志文件中,需要注意的是数据只是被写入文件系统中,并没有真正落盘,默认。
FSYNC_WAL:同步将数据写入日志文件并强制落盘。最严格的日志写入等级,可以保证数据不会丢失,但是性能相对比较差。
同样,除了在创建表的时候直接设置WAL存储级别,也可以通过客户端设置WAL持久化等级,代码:
put.setDurability(Durability.SYNC_WAL);
8.关于Compaction
hbase默认是自动进行Compaction,即hfile的自动合并操作,合并会带来较大的资源开销,因此我们需要合理的Compaction策略,一个是Compaction文件数量的合理设置,另一个是选择凌晨等数据写入较少的时候Compaction,需要采用手动Compaction,禁用自动Compaction。