在大数据领域中,有很多nosql 的数据库,典型的 hbase,可以实现大数据量下的快速查询,但是关系型数据的地位还是没办法替代。比如上个项目中,计算完的结果数据,还是会输出到关系型数据库当中。Flink 中没有提供关系型数据的connector,看到有小伙伴在问,怎么实现,就写个简单的demo。

Flink sink,都有两种方式,对外输出数据:

继承RichSinkFunction
实现OutputFormat接口

这里继承RichSinkFunction 实现 往 mysql 输出数据的sink。

mysql 表结构如下:

mysql> desc user;
+----------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| username | varchar(32) | NO | UNI | NULL | |
| password | varchar(32) | NO | | NULL | |
| sex | int(11) | YES | | 0 | |
| phone | varchar(18) | YES | | NULL | |
+----------+-------------+------+-----+---------+----------------+
5 rows in set (0.00 sec)

执行流程如下:

  kafka source -> map -> mysqlSink

1、继承RichSinkFunction

  主要代码如下:

env.addSource(source)
.map(li => {
val tmp = li.split(",")
new User(tmp(0), tmp(1), tmp(2)toInt, tmp(3))
})
.addSink(new MysqlSink)

MysqlSink:

import java.sql.{Connection, DriverManager, PreparedStatement, SQLException}
import org.apache.flink.configuration.Configuration
import org.apache.flink.streaming.api.functions.sink.{RichSinkFunction, SinkFunction}
import org.slf4j.{Logger, LoggerFactory} class MysqlSink extends RichSinkFunction[User] { val logger: Logger = LoggerFactory.getLogger("MysqlSink")
var conn: Connection = _
var ps: PreparedStatement = _
val jdbcUrl = "jdbc:mysql://192.168.229.128:3306?useSSL=false&allowPublicKeyRetrieval=true"
val username = "root"
val password = "123456"
val driverName = "com.mysql.jdbc.Driver" override def open(parameters: Configuration): Unit = { Class.forName(driverName)
try {
Class.forName(driverName)
conn = DriverManager.getConnection(jdbcUrl, username, password) // close auto commit
conn.setAutoCommit(false)
} catch {
case e@(_: ClassNotFoundException | _: SQLException) =>
logger.error("init mysql error")
e.printStackTrace()
System.exit(-1);
}
} /**
* 吞吐量不够话,可以将数据暂存在状态中,批量提交的方式提高吞吐量(如果oom,可能就是数据量太大,资源没有及时释放导致的)
* @param user
* @param context
*/
override def invoke(user: User, context: SinkFunction.Context[_]): Unit = {
println("get user : " + user.toString)
ps = conn.prepareStatement("insert into async.user(username, password, sex, phone) values(?,?,?,?)")
ps.setString(1, user.username)
ps.setString(2, user.password)
ps.setInt(3, user.sex)
ps.setString(4, user.phone) ps.execute()
conn.commit()
}
override def close(): Unit = {
if (conn != null){
conn.commit()
conn.close()
}
}
}

2、实现 OutputFormat 接口

  主要代码如下:

env.addSource(source)
.map(li => {
val tmp = li.split(",")
new User(tmp(0), tmp(1), tmp(2)toInt, tmp(3))
})
// .addSink(new MysqlSink1)
.writeUsingOutputFormat(new MysqlSink1)

MysqlSink1

import java.sql.{Connection, DriverManager, PreparedStatement, SQLException}
import org.apache.flink.api.common.io.OutputFormat
import org.apache.flink.configuration.Configuration
import org.slf4j.{Logger, LoggerFactory} class MysqlSink1 extends OutputFormat[User]{ val logger: Logger = LoggerFactory.getLogger("MysqlSink1")
var conn: Connection = _
var ps: PreparedStatement = _
val jdbcUrl = "jdbc:mysql://192.168.229.128:3306?useSSL=false&allowPublicKeyRetrieval=true"
val username = "root"
val password = "123456"
val driverName = "com.mysql.jdbc.Driver" override def configure(parameters: Configuration): Unit = {
// not need
} override def open(taskNumber: Int, numTasks: Int): Unit = {
Class.forName(driverName)
try {
Class.forName(driverName)
conn = DriverManager.getConnection(jdbcUrl, username, password) // close auto commit
conn.setAutoCommit(false)
} catch {
case e@(_: ClassNotFoundException | _: SQLException) =>
logger.error("init mysql error")
e.printStackTrace()
System.exit(-1);
}
} override def writeRecord(user: User): Unit = { println("get user : " + user.toString)
ps = conn.prepareStatement("insert into async.user(username, password, sex, phone) values(?,?,?,?)")
ps.setString(1, user.username)
ps.setString(2, user.password)
ps.setInt(3, user.sex)
ps.setString(4, user.phone) ps.execute()
conn.commit()
} override def close(): Unit = { if (conn != null){
conn.commit()
conn.close()
}
}
}

比较简单,就不贴测试结果了,如果吞吐量大,一定要改成批量提交的。

搞定

Flink MysqlSink 简单样例的更多相关文章

  1. extern外部方法使用C#简单样例

    外部方法使用C#简单样例 1.添加引用using System.Runtime.InteropServices; 2.声明和实现的连接[DllImport("kernel32", ...

  2. spring事务详解(二)简单样例

    系列目录 spring事务详解(一)初探事务 spring事务详解(二)简单样例 spring事务详解(三)源码详解 spring事务详解(四)测试验证 spring事务详解(五)总结提高 一.引子 ...

  3. velocity简单样例

    velocity简单样例整体实现须要三个步骤,详细例如以下: 1.创建一个Javaproject 2.导入须要的jar包 3.创建须要的文件 ============================= ...

  4. 自己定义隐式转换和显式转换c#简单样例

    自己定义隐式转换和显式转换c#简单样例 (出自朱朱家园http://blog.csdn.net/zhgl7688) 样例:对用户user中,usernamefirst name和last name进行 ...

  5. VC6 鼠标钩子 最简单样例

    Windows系统是建立在事件驱动的机制上的,说穿了就是整个系统都是通过消息的传递来实现的.而钩子是Windows系统中非常重要的系统接口,用它能够截获并处理送给其它应用程序的消息,来完毕普通应用程序 ...

  6. gtk+3.0的环境配置及基于gtk+3.0的python简单样例

    /*********************************************************************  * Author  : Samson  * Date   ...

  7. java 使用tess4j实现OCR的最简单样例

    网上很多教程没有介绍清楚tessdata的位置,以及怎么配置,并且对中文库的描述也存在问题,这里介绍一个最简单的样例. 1.使用maven,直接引入依赖,确保你的工程JDK是1.8以上 <dep ...

  8. 使用SALT-API进入集成开发的简单样例

    测试的时候,可以CURL -K,但真正作集成的时候,却是不可以的. 必须,不可以让TOKEN满天飞吧. 现在进入这个阶段了.写个样例先: import salt import salt.auth im ...

  9. VB.net数据库编程(03):一个SQLserver连接查询的简单样例

    这个样例,因为在ADO.net入门已经专门学了,再次进行复习 一下. 主要掌握连接字串的情况. 过程就是: 1.引用System.Data.SqlClient.而Access中引用 的是System. ...

随机推荐

  1. git如何统计代码行数

    1.根据用户名时间段统计 git log --author="username" --since=2018-01-01 --until=2019-12-31 --pretty=tf ...

  2. C# 线程小结

    进程与线程 什么是进程? 当一个程序开始运行时,它就是一个进程,进程包括运行中的程序和程序所使用到的内存和系统资源. 而一个进程又是由多个线程所组成的. 什么是线程? 线程是程序中的一个执行流,每个线 ...

  3. 浏览器URL中“#” “?” &“”作用

    1. # 10年9月,twitter改版.一个显著变化,就是URL加入了"#!"符号.比如,改版前的用户主页网址为http://twitter.com/username改版后,就变 ...

  4. LIO -SCSI target

    2010年底,LIO 项目获选成为新的内核态的 SCSI target,取代原有的用户态的 STGT 项目.当时有两个主要的竞争项目(LIO和SCST),都在努力将代码并入主线内核.本文将比较着两个项 ...

  5. CF1163E Magical Permutation【线性基,构造】

    题目描述:输入一个大小为\(n\)的正整数集合\(S\),求最大的\(x\),使得能构造一个\(0\)到\(2^x-1\)的排列\(p\),满足\(p_i\oplus p_{i+1}\in S\) 数 ...

  6. (27)打鸡儿教你Vue.js

    v-for 数组参数的顺序 当含有index时,以前传递的参数顺序是: (index, value).现在(value, index) ready替换使用新的mounted钩子代替,通过使用mount ...

  7. UOJ310. 【UNR #2】黎明前的巧克力 [FWT]

    UOJ 思路 显然可以转化一下,变成统计异或起来等于0的集合个数,这样一个集合的贡献是\(2^{|S|}\). 考虑朴素的\(dp_{i,j}\)表示前\(i\)个数凑出了\(j\)的方案数,发现这其 ...

  8. 印象笔记作为todo(GTD相关)的一个尝试

    印象笔记作为todo(GTD相关)的一个尝试 上来说结果: 失败 原则上的原因: 印象笔记作为一个比较重的笔记, 重点也不在于这一点, 虽然是可以新建清单之类的. 还是比较小巧的好一些. 最后使用的软 ...

  9. jenkins之SSH Publishers环境变量

    我使用的是docker部署jenkins,使用172.16.1.245作为部署服务器. 1.问题 在SSH Publishers里执行的环境变量,不是ssh server主机设置的环境变量,这样会导致 ...

  10. Hadoop hadoop 之hdfs数据块修复方法

    hadoop 之hdfs数据块修复方法: .手动修复 hdfs fsck / #检查集群的健康状态 hdfs debug recoverLease -path 文件位置 -retries 重试次数 # ...