实时即未来,大数据项目车联网之原始数据实时ETL落地HBase
1. 原始数据实时ETL落地HBase
原始数据落地hive并且落地hbase,主要有两个作用
-
存储hive数据用作离线分析经过ETL后的原始数据;存储hbase数据用作实时指标分析经过ETL后的原始数据
-
一份数据作为备份:即可把存储hive数据看做是hbase数据的备份,也可把存储hbase数据看做是hive数据的备份
1 rowkey设计原则和方法
rowkey设计首先应当遵循三大原则:
1 RowKey的设计原则
1 rowkey长度原则
rowkey是一个二进制码流,可以为任意字符串,最大长度为64kb,实际应用中一般为10-100bytes,它以byte[]形式保存,一般设定成定长。
一般越短越好,尽量不要超过16个字节,注意原因如下:
目前操作系统都是64位系统,内存8字节对齐,控制在16字节,8字节的整数倍利用了操作系统的最佳特性。
l hbase将部分数据加载到内存当中,如果rowkey过长,内存的有效利用率就会下降。
2 rowkey散列原则
如果rowkey按照时间戳的方式递增,不要将时间放在二进制码的前面,建议将rowkey的高位字节采用散列字段处理,由程序随即生成。低位放时间字段,这样将提高数据均衡分布,各个regionServer负载均衡的几率。
如果不进行散列处理,首字段直接使用时间信息,所有该时段的数据都将集中到一个regionServer当中,这样当检索数据时,负载会集中到个别regionServer上,造成热点问题,会降低查询效率。
3 rowkey唯一原则
必须在设计上保证其唯一性,rowkey是按照字典顺序排序存储的,因此,设计rowkey的时候,要充分利用这个排序的特点,将经常读取的数据存储到一块,将最近可能会被访问的数据放到一块。但是这里的量不能太大,如果太大需要拆分到多个节点上去。
2 常用的rowkey设计方法
2.1 Salt加盐
Salt是将每一个Rowkey加一个前缀,前缀使用一些随机字符,使得数据分散在多个不同的Region,达到Region负载均衡的目标。
比如在一个有4个Region(注:以 [ ,a)、[a,b)、[b,c)、[c, )为Region起至)的HBase表中,
加Salt前的Rowkey:abc001、abc002、abc003\
我们分别加上a、b、c前缀,加Salt后Rowkey为:a-abc001、b-abc002、c-abc003\
可以看到,加盐前的Rowkey默认会在第2个region中,加盐后的Rowkey数据会分布在3个region中,理论上处理后的吞吐量应是之前的3倍。由于前缀是随机的,读这些数据时需要耗费更多的时间,所以Salt增加了写操作的吞吐量,缺点是同时增加了读操作的开销。
2.2 Hash散列或者Mod
用Hash散列来替代随机Salt前缀的好处是能让一个给定的行有相同的前缀,这在分散了Region负载的同时,使读操作也能够推断。确定性Hash(比如md5后取前4位做前缀)能让客户端重建完整的RowKey,可以使用get操作直接get想要的行。
例如将上述的原始Rowkey经过hash处理,此处我们采用md5散列算法取前4位做前缀,结果如下:
9bf0-abc001 (abc001在md5后是9bf049097142c168c38a94c626eddf3d,取前4位是9bf0)
7006-abc002
95e6-abc003
若以前4个字符作为不同分区的起止,上面几个Rowkey数据会分布在3个region中。实际应用场景是当数据量越来越大的时候,这种设计会使得分区之间更加均衡。
如果Rowkey是数字类型的,也可以考虑Mod方法。
2.3 Reverse反转
针对固定长度的Rowkey反转后存储,这样可以使Rowkey中经常改变的部分放在最前面,可以有效的随机Rowkey。
反转Rowkey的例子通常以手机举例,可以将手机号反转后的字符串作为Rowkey,这样的就避免了以手机号那样比较固定 开头(137x、15x等)导致热点问题,
这样做的缺点是牺牲了Rowkey的有序性。
2 实时ETL数据落地hbase步骤分析
数据落地HBase
-
自定义sink实现:
-
目前有两种方法:
第一种继承RichSinkFunction类实现(采用)
自定义sink,继承RichSinkFunction类
重写方法,实现数据写入hbase逻辑
在KafkaSourceDataTask主任务中调用
第二种实现OutputFormat接口
自定义Sink中RichSinkFunction对象
l RichSinkFunction抽象类是我们自定义数据输出需继承的对象
- 继承了AbstractRichFunction,实现了RinkFunction接口,定义了函数对象的生命周期,open、close方法,拥有不可被序列化的RuntimeContext对象
u AbstractRichFunction抽象类
用户自定义函数抽象存根实现,存根实现指的是指向”RichFunction”实现
定义了函数生命周期方法:初始化(open方法)、对象销毁(close方法)
指定所在函数运行时执行上下文对象的方法
SinkFunction接口
用户自定义sink函数接口
实现写入获得的记录到自定义sink中
- 该函数每一条记录会被回调一次
定义Context接口
-
获得当前执行sink时间
-
获得当前event水印
-
获得当前输入记录的timestamp
3 实时ETL数据落地hbase实现
启动hbase集群
start-hbase.sh |
---|
进入hbase命令行
hbase shell |
---|
自定义sink,继承RichSinkFunction类
- 创建原始数据实时ETL落地hbase表:“maynor_src”
create ‘maynor_src’,‘cf’
n json解析成功后需要存到hbase的数据类型为:
- 创建全局变量,实现使用hbase客户端写入数据到hbase
/
需求:将正常的数据实时的写入到hbase中
实现思路:
1)继承自RichSinkFunction对象
2)重写父类的方法
2.1:open
实现hbase的连接,然后获得table对象
2.2:close
释放资源,关闭hbase的连接
2.3:invoke
创建put实例,将数据一条条的写入到hbase中
/
- 点赞
- 收藏
- 关注作者
评论(0)