Spark读HBase写MySQL
1 Spark读HBase
Spark读HBase黑名单数据,过滤出当日新增userid,并与mysql黑名单表内userid去重后,写入mysql。
def main(args: Array[String]): Unit = {
@volatile var broadcastMysqlUserids: Broadcast[Array[String]] = null
val today = args(0)
val sourceHBaseTable = PropertiesUtil.getProperty("anticheat.blacklist.hbase.tbale")
val sinkMysqlTable = PropertiesUtil.getProperty("anticheat.blacklist.mysql.dbtable")
val zookeeper = PropertiesUtil.getProperty("anticheat.blacklist.zookeeper.quorum")
val zkport = PropertiesUtil.getProperty("anticheat.blacklist.zookeeper.port")
val znode = PropertiesUtil.getProperty("anticheat.blacklist.zookeeper.znode")
//创建SparkSession
val sparkconf = new SparkConf().setAppName("").set("spark.serializer", "org.apache.spark.serializer.KryoSerializer")
val sc = new SparkContext(sparkconf)
val spark = AnticheatUtil.SparkSessionSingleton.getInstance(sc.getConf)
//配置hbase参数
val conf = HBaseConfiguration.create
conf.set("hbase.zookeeper.quorum", zookeeper)
conf.set("hbase.zookeeper.property.clientPort", zkport)
conf.set("zookeeper.znode.parent", znode)
conf.set(TableInputFormat.INPUT_TABLE, sourceHBaseTable)
// 从数据源获取数据
val hbaseRDD = sc.newAPIHadoopRDD(conf,classOf[TableInputFormat],classOf[ImmutableBytesWritable],classOf[Result])
//读取mysql表,并将mysql表中的userid广播出去,用于去重
broadcastMysqlUserids = get_mysql_user_blacklist(spark,sinkMysqlTable)
//获取当日新增userid数据组装成与mysql表结构一致的对象rdd
val records_userid_rdd = get_new_blacklist_rdd(hbaseRDD,today,broadcastMysqlUserids)
//将当日新增userid数据存入mysql
save_blacklist_to_mysql(records_userid_rdd,today,spark,sinkMysqlTable)
}
2 Spark读MySQL表广播出去
/**
* Spark读Mysql用户黑名单表,将黑名单中所有userid赋予广播变量
* @param spark
* @return
*/
def get_mysql_user_blacklist(spark: SparkSession,table :String) :Broadcast[Array[String]] = {
@volatile var broadcastMysqlUserids: Broadcast[Array[String]] = null
val url = PropertiesUtil.getProperty("anticheat.blacklist.mysql.url")
val user = PropertiesUtil.getProperty("anticheat.blacklist.mysql.user")
val password = PropertiesUtil.getProperty("anticheat.blacklist.mysql.password")
import spark.implicits._
val mysql_userids_rdd = spark.sqlContext.read
.format("jdbc")
.option("url",url)
.option("dbtable",table)
.option("user",user)
.option("password",password)
.load()
.map(record => {
val userid = record.getString(0)
userid
})
if(broadcastMysqlUserids !=null){
broadcastMysqlUserids.unpersist()
}
broadcastMysqlUserids = spark.sparkContext.broadcast(mysql_userids_rdd.collect())
println(s"broadcastMysqlUserids.size= ${broadcastMysqlUserids.value.size}")
broadcastMysqlUserids
}
3 构建黑名单数据对象rdd
/**
* 构建新增userid数据写入mysql
* @param hbaseRDD
* @param today
* @return
*/
def get_new_blacklist_rdd(hbaseRDD: RDD[(ImmutableBytesWritable, Result)],today: String,broadcastMysqlUserids: Broadcast[Array[String]]): RDD[BlackList] = {
val records_userid_rdd : RDD[BlackList] = hbaseRDD.filter(line =>{
//过滤出当日新增userid
var flag = false //默认非当日新增
val userid = Bytes.toString(line._2.getRow)
val dt = Bytes.toString(line._2.getValue(Bytes.toBytes("user"), Bytes.toBytes("dt")))
val did_dt = Bytes.toString(line._2.getValue(Bytes.toBytes("user"), Bytes.toBytes("did_dt")))
/* 判断为当日新增userid同时需满足三个条件:
1. 用户维度加入时间dt=today
2. 或者用户维度加入时间dt=null 且设备维度加入时间did_dt=today
3. 并且不在mysql黑名单表中
*/
if(today.equals(dt) || (dt==null && today.equals(did_dt))){
//broadcastMysqlUserids.value.search(userid).isInstanceOf[InsertionPoint]调用scala 二分查找函数,注意此函数找到返回false
if(broadcastMysqlUserids.value.search(userid).isInstanceOf[InsertionPoint]){
//以上三个条件全满足,表示为当日新增,flag 赋值为 true
flag = true
}
}
flag
}).map(record =>{
//获取新增用户userid,加入黑名单时间设为today,其余字段设为默认值
val userid = Bytes.toString(record._2.getRow)
val day = Integer.parseInt(today)
BlackList(userid,day,null,0,"system")
})
records_userid_rdd
}
case class BlackList(userid: String, dt: Int, update_time: Timestamp,delete_flag: Int,operator : String)
4 Spark写MySQL
/**
* 将userid黑名单数据写入mysql
* @param blacklist_rdd
* @param today
* @param spark
*/
def save_blacklist_to_mysql(blacklist_rdd: RDD[BlackList],today: String,spark: SparkSession,table :String): Unit ={
val url = PropertiesUtil.getProperty("anticheat.blacklist.mysql.url")
val user = PropertiesUtil.getProperty("anticheat.blacklist.mysql.user")
val password = PropertiesUtil.getProperty("anticheat.blacklist.mysql.password")
import spark.implicits._
val records_userid_dataset = blacklist_rdd.toDS()
records_userid_dataset.write
.format("jdbc")
.option("url",url)
.option("dbtable",table)
.option("user",user)
.option("password",password)
.mode(SaveMode.Append)
.save()
}
5 注意问题
数据存入Mysql注意事项
尽量先设置好存储模式
默认为SaveMode.ErrorIfExists模式,该模式下,如果数据库中已经存在该表,则会直接报异常,导致数据不能存入数据库.另外三种模式如下:
SaveMode.Append 如果表已经存在,则追加在该表中;若该表不存在,则会先创建表,再插入数据;
SaveMode.Overwrite 重写模式,其实质是先将已有的表及其数据全都删除,再重新创建该表,最后插入新的数据;
SaveMode.Ignore 若表不存在,则创建表,并存入数据;在表存在的情况下,直接跳过数据的存储,不会报错。

Spark读HBase写MySQL的更多相关文章
- spark读文件写mysql(java版)
package org.langtong.sparkdemo; import com.fasterxml.jackson.databind.ObjectMapper; import org.apach ...
- IDEA中Spark读Hbase中的数据
import org.apache.hadoop.hbase.HBaseConfiguration import org.apache.hadoop.hbase.io.ImmutableBytesWr ...
- IDEA中 Spark 读Hbase 报错处理:
SLF4J: Actual binding is of type [org.slf4j.impl.Log4jLoggerFactory] // :: ERROR RecoverableZooKeepe ...
- Spark读Hbase优化 --手动划分region提高并行数
一. Hbase的region 我们先简单介绍下Hbase的架构和Hbase的region: 从物理集群的角度看,Hbase集群中,由一个Hmaster管理多个HRegionServer,其中每个HR ...
- Spark 读 Hbase
package com.grady import org.apache.hadoop.hbase.HBaseConfiguration import org.apache.hadoop.hbase.c ...
- spark读文件写入mysql(scala版本)
package com.zjlantone.hive import java.util.Properties import com.zjlantone.hive.SparkOperaterHive.s ...
- 用MapReduce读HBase写MongoDB样例
1.版本信息: Hadoop版本:2.7.1 HBase版本:1.2.1 MongDB版本:3.4.14 2.HBase表名及数据: 3.Maven依赖: <dependency> < ...
- spark sql读hbase
项目背景 spark sql读hbase据说官网如今在写,但还没稳定,所以我基于hbase-rdd这个项目进行了一个封装,当中会区分是否为2进制,假设是就在配置文件里指定为#b,如long#b,还实用 ...
- Spark-读写HBase,SparkStreaming操作,Spark的HBase相关操作
Spark-读写HBase,SparkStreaming操作,Spark的HBase相关操作 1.sparkstreaming实时写入Hbase(saveAsNewAPIHadoopDataset方法 ...
随机推荐
- js的短路
短路问题经常是发生在逻辑运算符中的逻辑与(&&).逻辑或(||) 1.逻辑或(||) 他是一真则真,当逻辑或前面的表达式结果为1或true时,逻辑或后面的表达式是不会执行的 2.逻辑与 ...
- vue-cli(vue脚手架) 简单使用
1.vue-cli 作用 vue-cli作为vue的脚手架,可以帮助我们在实际开发中自动生成vue.js的模板工程. 2.vue-cli 使用 a. 安装全局vue-cli npm install v ...
- 2015-10-26 c#2
二.值类型和引用类型 2.1 值类型:所有的数值类型都是值类型(short int long float double ...),枚举,布尔类型,结构 2.2 引用类型:对象 ,字符串,objec ...
- Win10系列:C#应用控件进阶8
LineGeometry LineGeometry控件通过指定直线的起点和终点来定义线.LineGeometry对象无法进行自我绘制,因此同样需要使用 Path元素来辅助呈现.LineGeometry ...
- lr-web services协议
1.web services协议简介 web services协议是建立可交互操作的分布式应用程序的新平台,它通过一系列标准和协议来保证程序之间的动态链接,其中最基本的协议包括soap,wsdl,ud ...
- selenium自动化实例: 多层框架中关于iframe的定位,以及select下拉框选择
对于一个自动化的初学者来说会很常见的遇到元素明明存在却始终定位不到, 从而导致脚本报错,当然定位不到元素的原因很多, 其中一种就是多层框架iframe导致的 下方截图示意: 下方为写脚本时候的示例并其 ...
- pyCharm-激活码(2018)
最近使用pycharm的时候,用的是很久以前的激活地址 于是网上到处寻找最新地址,然而 网上之前分享的激活地址已经多半过期, 于是找朋友帮忙,终于找到一个可用的了 1.选择 Activate new ...
- 小学四则运算编程(c#)
---恢复内容开始--- 预计耗时与实际耗时: 代码基本完善后,对代码进行了性能改善,使用递归并减少了一些不必要的代码. 项目分析:二年级以下无乘除,四年级以下无小数 性能: 类图: 通过这次个人项目 ...
- OO第四次作业总结
一:测试与正确性论证的效果差异 首先,测试和正确性论证都是对程序的可靠与否,是否有误进行测试,从整体上来看,测试多偏向于实践,而正确性论证则大多偏向于理论. 测试:测试首先是构造一组测试样例,之后将程 ...
- 使用飞冰组件关于点击行回填在input内(React)
import { Table,Grid } from "@icedesign/base"; import { FormBinderWrapper as IceFormBinderW ...