1、前言算法
关于数据落地方面,HBase官网也有相关介绍。本文主要介绍一下实际工做中涉及的数据存储方面的一些经验和技巧,主要涉及表rowkey设计、数据落地方案数据库
2、表设计apache
相对于MySQL等关系型数据库而言,HBase也有相应的相似库和表的概念,其中MySQL的库对应于HBase的NameSpace (0.95以上版本才支持), 表对应于HBase的表。对于NameSpace来讲,HBase默认有两类:default和hbase, default中存放的实际数据的表,hbase中存放的是系统内建表,如meta元数据表。bash
2.1 ROWKEY设计架构
HBase表在设计过程当中,rowkey设计很关键,若是rowkey设计很差,可能会出现热点、负载不均衡、数据冗余等问题。常见的ROWKEY设计通常须要遵循几个原则:app
1) rowkey要唯一: 组成rowkey的字段须要全局唯一,好比像支付订单类的系统,通常存在交易单号,交易时间等,能够把这两个字段组合成rowkey, 这样在scan数据时还能够按单号还时间来批量扫描数据以提升效率分布式
2) 避免热点问题: 在考虑唯一性以后,还须要考虑热点问题,hbase是分布式存储系统,数据存储时按region维度进行管理,region会分配到各regionserver上,若是rowkey设计很差,会存在同一类型的数据会集中在某几个region上,致使数据写入和访问时出现热点现象,像这类问题很容易致使regionserver宕机现象,影响集群稳定性。像咱们生产环境的下rowkey设计,还会考虑一个分桶规则,分桶的规则是好比将单号后三位做为分桶号,同时在建表时指定SPLITS参数,预拆分表的region。oop
a. 建表时怎么指定region数呢,以下建表语句,即指定表预先分配3个分桶,这样以001,002,003结尾单号的数据会存储到001,002,003分桶中,同时这些分桶会被随机分配各到各台regionserver。优化
create 'test', {SPLITS =>['001', '002', '003']}
b. rowkey设计形式相似于以下:分桶号#交易时间#交易单号 spa
000#2017-01-27 00:00:00#11111111000
3)业务需求:通常业务在查询hbase数据时,会要求你的数据必须能实现多维度查询和按时间段,用户ID进行批量提取数据等。对于多维度查询方面,hbase因不支持二级索引,致使实现这类多维度查询有很大难度,在咱们集群中,用了一个折中方案,就是将索引字段独立出来建一个单独的索引表,索引表的KEY值 为索引字段加时间组合成rowkey, 索引表的value值为数据表的rowkey值, 这样经过索引字段先扫描索引表,获得数据表的rowkey后,再扫主表,获得具体的交易数据。这样就间接实现相似二级索引功能。具体设计以下:
索引表设计: 索引表的rowkey主要是将单号和交易时间组合,同时为避免单号存在热点问题,将单号反转后处理,以下面rowkey:
#单号:123456,交易时间:2017-01-27 00:00:00 rowkey: 654321#2017-01-27 00:00:00
value: 456#2017-01-27 00:00:00#123456
2.2 表设计
hbase表在设计时,须要评估业务表数据量的大小,像咱们的业务数据单表可能日均数据量能达到20亿级别,若是在设计时只设计单表的话,那后续在数据维护、业务使用时将会碰到很大的麻烦,因此咱们考虑的是将同一类业务表,设计成按月分表,设计成按月分表的话,对某个月的表的操做能够不影响其它月份的表,尽可能减小受影响的数据范围,同时操做月表,数据也易迁移,使集群受影响的程度尽可能减小。上面介绍到分桶的概念,对于按月分的表,根据数据量的大小,预先规划region的数量,会使数据尽可能分布均衡。
表设计时,还须要考虑列簇数量,列族的话不宜过多,1-3个为好,越多列族相互之间受影响也越大,同时影响集群数据稳定性。考虑到咱们生产环境的业务数据是从MySQL表过来的数据,因此只设计了一个列族,方便操做管理。表在建立时,会带一些参数来优化数据存储,以下所示, 会带上hfile文件的最大size, region拆分规则,列族名,BloomFilter模式为ROW模式,压缩算法为snappy, 块大小,blockcache等。
create 'test', {METHOD => 'table_att', MAX_FILESIZE => '549755813888', METADATA => {'SPLIT_POLICY' => 'org.apache.hadoop.hbase.regionserver.DisabledRegionSplitPolicy'}}, {NAME => 'cf', DATA_BLOCK_ENCODING => 'DIFF', BLOOMFILTER => 'ROW', REPLICATION_SCOPE => '0', VERSIONS => '1', COMPRESSION => 'SNAPPY', MIN_VERSIONS => '0', KEEP_DELETED_CELLS => 'false', BLOCKSIZE => '65536', IN_MEMORY => 'false', BLOCKCACHE => 'true'}, {SPLITS =>['001','002','003']}
3、数据落地方案
HBASE数据场景不少,业务产生的数据如何入到Hbase呢,对于实时数据而言,通常会用到一些组件,如kafaka, storm, spark等, 经过采集Agent将业务数据进行清洗,将数据规范成指定格式的消息记录,而后写入到Kafaka, 进行数据分发,再经过storm集群进行数据消费到hbase, 这种模式也是业界很常见的模式。对于咱们的集群,因为业务数据过于庞大,业务对数据时效性也很高,因此数据通常先入MySQL, 经过binlog采集解析入到消息队列再通过Storm集群进行消费入hbase。这种架构的话,对于采集要求很高,不能有数据丢失,业界关于binlog实时采集国内比较有名的就是淘宝的canal组件,该组件能够高效稳定采集业务DB的数据,并实时记录binlog采集位置,一旦采集Agent机器故障,支持将任务切换到其它机器继续采集,对于业务DB若是出现故障,能够及时告警发现异常。通过canal清洗的数据进入到kafaka,kafaka的优势我就不介绍了,网上不少资料介绍,Kafaka的数据再通过storm程序批量同步到HBase,实现实时数据入HBase这一方案。
因数据分析,业务查询须要,需将存储在MySQL的历史数据也同步到HBase,但因历史数据已无binlog, 因此须要考虑其它方案将数据同步到HBase, 对于这种场景,通常是用bulkload将数据同步到Hbase,咱们也是用bulkload,由于原生的bulkload使用仍是用些问题,没法适应业务数据表和索引表的导入,因此本身部门专门定制了bulkload以适应咱们的业务场景。
4、总结
本文简单的介绍了一下HBase表设计相关的经验和数据落地方面的经验,不少经验都是在踩过坑以后才有的优化,仍是那句话,没有问题就没有进步,但愿后面少踩些坑。