Spark Streaming实时写入数据到HBase
一、概述
在实时应用之中,难免会遇到往NoSql数据如HBase中写入数据的情景。题主在工作中遇到如下情景,需要实时查询某个设备ID对应的账号ID数量。踩过的坑也挺多,举其中之一,如一开始选择使用NEO4J图数据库存储设备和账号的关系,当然也有其他的数据,最终构成一个复杂的图关系,但是这个图数据库免费版是单机安装(集群要收费),在实时写入和查询关系的时候,导致我们一台服务器内存和cpu损耗严重,为了保证Hadoop集群的稳定性,只好替换掉这个数据库,采用流行的HBase。本文就HBase的使用心得做如下记录。
二、解决方案
1.rowkey设计:设备id是32位字母、数字组成的串,考虑到HBase长表扫描的查询最快,所以rowkey的设计方式为,设备ID+账号ID拼接而成,这样在扫描某个设备ID时会很快计算出条数。
2.HBase表设计:在创建表的时候采用预分区建表,因为这样的,如果知道hbase数据表的rowkey的分布情况,就可以在建表的时候对hbase进行region的预分区,这样做的好处是防止大数据量插入的热点问题,提高数据插入的效率。rowkey是字母或者数字开头,所以建表语句如下(数据量再大的时候还可以在细分分区):
create 'T_TEST', 'data', SPLITS => ['0', '1','2', '3','4', '5','6','7','8','9','a', 'b', 'c', 'd', 'e', 'f', 'g']
此处入坑:创建表的时候将HBase表映射到Hive外部表,语句如下。这样做是为了方便导入历史数据,但是Hive跑批将历史数据导入之后,从HBase查询已经导入的某一数据的时候,无法查询导数据,也无法通过API写入到HBase,这个问题很诡异,后来想了下Hive导入的数据编码和HBase的不同,于是重新将表删除,不采用映射表,直接使用Spark将历史数据导入,问题解决。
CREATE external TABLE tmp.H_T_TEST(key string ,num string)
STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler'
WITH SERDEPROPERTIES ("hbase.columns.mapping" = ":key,data:num")
TBLPROPERTIES ("hbase.table.name" = "T_TEST");
3.设计好rowkey和表之后,我们就开始写Spark代码了。
此处入坑,我把HBase的连接池写在了和Spark的同一位置,这样会遇到一个问题,Spark程序运行的时候报HBaseConnection没有序列化,按照网上的做法,将对象加上 @transient注解,虽然不报错误,还是无法将数据写入到Hba之中。后来经过查找,找到了解决办法,将HBase的连接放到消息的循环之内,即一个分区建立一个HBase连接,代码如下。
def main(args: Array[String]): Unit = {
val sc: SparkContext = SparkUtil.createSparkContext(this.getClass.getSimpleName)
val ssc: StreamingContext = new StreamingContext(sc, Seconds(10))
val messages = SparkUtil.createDStreamFromKafka(
"T_TEST",
topicSet,
ssc)//创建消息接收器 messages.foreachRDD(rdd => {
rdd.foreachPartition(partitionRecords => {//循环分区
try {
val connection = HBaseUtil.getHbaseConn //获取HBase连接,分区创建一个连接,分区不跨节点,不需要序列化
partitionRecords.foreach(s => {
val data = JSON.parseObject(s._2)//将数据转化成JSON格式
val tableName = TableName.valueOf("T_TEST")
val table = connection.getTable(tableName)//获取表连接 val put = new Put(Bytes.toBytes(data.getString("id1") + "_" + data.getString("id2")))
put.addColumn(Bytes.toBytes("data"), Bytes.toBytes("num"), Bytes.toBytes("1")) Try(table.put(put)).getOrElse(table.close())//将数据写入HBase,若出错关闭table
table.close()//分区数据写入HBase后关闭连接
})
} catch {
case e: Exception => logger.error("写入HBase失败,{}", e.getMessage)
}
})
})
ssc.start()
ssc.awaitTermination() }
至此问题解决,数据正常,还没出现过问题,等待时间验证吧。
4.历史数据导入,在导入历史数据的时候,由于数据放在了Hive的两个不同表之中,一开始想要一次性读入,使用Spark SQL的dataframe,创建一个hivecontext,写HiveSQL将两个表结果执行union all操作,但是Spark程序报rpc错误。将两个表的结果分别查出,使用dataframe 的union all操作,也是不行,也是rpc错误,查了很多资料,还是没解决,莫名其妙的错误,后来两个表分开执行导入历史数据,问题不再出现,可能Spark还是不够成熟,总是遇到莫名其妙的问题。
三、总结
在使用Hbase的时候要预分区。不要为了方便使用Hive外部映射表。HBase的连接池要放在分区循环开始的地方,不然创建很多的连接,会导致HBase垮掉。
Spark Streaming实时写入数据到HBase的更多相关文章
- Spark Streaming接收Kafka数据存储到Hbase
Spark Streaming接收Kafka数据存储到Hbase fly spark hbase kafka 主要参考了这篇文章https://yq.aliyun.com/articles/60712 ...
- 【转】Spark Streaming 实时计算在甜橙金融监控系统中的应用及优化
系统架构介绍 整个实时监控系统的架构是先由 Flume 收集服务器产生的日志 Log 和前端埋点数据, 然后实时把这些信息发送到 Kafka 分布式发布订阅消息系统,接着由 Spark Streami ...
- 【慕课网实战】Spark Streaming实时流处理项目实战笔记十之铭文升级版
铭文一级: 第八章:Spark Streaming进阶与案例实战 updateStateByKey算子需求:统计到目前为止累积出现的单词的个数(需要保持住以前的状态) java.lang.Illega ...
- Spark练习之通过Spark Streaming实时计算wordcount程序
Spark练习之通过Spark Streaming实时计算wordcount程序 Java版本 Scala版本 pom.xml Java版本 import org.apache.spark.Spark ...
- Spark Streaming实时计算框架介绍
随着大数据的发展,人们对大数据的处理要求也越来越高,原有的批处理框架MapReduce适合离线计算,却无法满足实时性要求较高的业务,如实时推荐.用户行为分析等. Spark Streaming是建立在 ...
- 【Streaming】30分钟概览Spark Streaming 实时计算
本文主要介绍四个问题: 什么是Spark Streaming实时计算? Spark实时计算原理流程是什么? Spark 2.X下一代实时计算框架Structured Streaming Spark S ...
- Spark Streaming揭秘 Day16 数据清理机制
Spark Streaming揭秘 Day16 数据清理机制 今天主要来讲下Spark的数据清理机制,我们都知道,Spark是运行在jvm上的,虽然jvm本身就有对象的自动回收工作,但是,如果自己不进 ...
- 新闻网大数据实时分析可视化系统项目——19、Spark Streaming实时数据分析
1.Spark Streaming功能介绍 1)定义 Spark Streaming is an extension of the core Spark API that enables scalab ...
- 通过Spark Streaming处理交易数据
Apache Spark 是加州大学伯克利分校的 AMPLabs 开发的开源分布式轻量级通用计算框架. 由于 Spark 基于内存设计,使得它拥有比 Hadoop 更高的性能(极端情况下可以达到 10 ...
随机推荐
- /bin/sh 与 /bin/bash 的区别
/bin/sh 与 /bin/bash 的区别,用 : 截取字符串不是POSIX 标准的. 区别 sh 一般设成 bash 的软链 (symlink) ls -l /bin/sh lrwxrwxrwx ...
- HUST 1376 Random intersection
神题.同学指教.1秒AC...http://blog.csdn.net/jtjy568805874/article/details/50724656 #include<cstdio> #i ...
- HUST 1351 Group
(莫名其妙的被一个叫布布扣的网站收录了......什么鬼) 简单DP.dp[i][j]表示把前i个数字分成j段的最优解, 递推式很容易写: (其中sum[]是前缀和:p <= i - L,并且前 ...
- Java 的Object类
1.toString()是Objectde的方法,如果不重写,直接输出对象或者用对象调用toString()输出是会输出包名.类名@对象哈希码的无符号十六进制表示 子类如果重写了这个方法,可以隐式调用 ...
- WKWebKit基础
UIWebView & UIWebViewDelegate 这个两个东西在 WKWebKit 中被重构成 14 个类 3 个协议. WKWebKit Framework Classes WKB ...
- NRF24L01无线通讯模块驱动
NRF24L01 无线模块,采用的芯片是 NRF24L01,该芯片的主要特点如下: )2.4G 全球开放的 ISM 频段,免许可证使用. )最高工作速率 2Mbps,高校的 GFSK 调制,抗干扰能力 ...
- 推荐一款非常好用的java反编译工具(转)
源: 推荐一款非常好用的java反编译工具
- 获取linq生成的sql语句
命名空间:using System.Data.Objects; var query = db.TxtRes.Join(db.LangRes, a => new { id1 = a.ResID, ...
- 关于jquery的$each((Object, function(p1, p2)用法
通过它,你可以遍历对象.数组的属性值并进行处理. 使用说明 each函数根据参数的类型实现的效果不完全一致: 1.遍历对象(有附加参数) $.each(Object, function(p1, p2) ...
- TFS2013 升级至TFS2015及项目的创建
TFS2015已发布想体验下新特性 由于现有数据库已经是SQLSERVER2012 SP1 开发工具VS2013 都符合升级要求 现在体验下吧 1.先下载TFS2015 运行安装向导一路NEXT 直至 ...