前言

下面这篇文章是使用Flink的Sink 写出数据到Redis和MySQL

Flink之Sink写入Redis和MySQL

Flink需要添加Sink的时候,需要自己去添加写Sink,我们可以实现SinkFunction,或者我们也可以继承RichSinkFunction,RichSinkFunction是实现了SinkFunction和继承了一个AbstractRichFunction,而增强主要是在AbstractRichFunction里面是有生命周期函数,这个对我们使用Sink的时候非常重要

// --------------------------------------------------------------------------------------------
// Default life cycle methods
// -------------------------------------------------------------------------------------------- @Override
public void open(Configuration parameters) throws Exception {} @Override
public void close() throws Exception {}

具体是否可以使用我们可以在官网里面查询你的数据库是否可以支持Source和Sink,下面这个是在1.15的文档下,可能后面社区会推出更多的支持,大家可以去官网中去看Overview | Apache Flink

Connectors source sink
Kafka 支持 支持
Cassandra 不支持 支持
Kinesis 支持 支持
Elasticsearch 不支持 支持
FileSystem 不支持 支持
RabbitMQ 支持 支持
Google PubSub 支持 支持
Hybrid Source 支持 不支持
NiFi 支持 支持
Pulsar 支持 不支持
JDBC 支持 不支持
ActiveMQ 支持 支持
Flume 不支持 支持
Redis 不支持 支持
Akka 不支持 支持
Netty 支持 不支持

Sink

下面我们来看一个例子吧,这个是日志数据,本次例子也是自己来模拟的

202512120010,c.com,2000
202512120010,c.com,5000
202512120010,a.com,6000
202512120010,c.com,1000
202512120010,b.com,2000
202512120010,a.com,2000

下面的是一个例子,里面有两个例子,一个是写入MySQL的,具体整个函数的处理就是根据域名进行点击量的统计,首先我们需要对数据进行转化成一个Access实体,然后再进行FlatMap转化,你可以看到添加一个Sink写出数据也是通过stream.addSink()添加一个Sink来写出数据。

public static void toMySql(StreamExecutionEnvironment env) {
DataStreamSource<String> source = env.readTextFile("D:/code/flink/coding510/com.dy.flink/data/access.log");
SingleOutputStreamOperator<Access> mapStream = source.map(new MapFunction<String, Access>() {
@Override
public Access map(String value) throws Exception {
String[] splits = value.split(",");
Long time = Long.parseLong(splits[0].trim());
String domain = splits[1].trim();
Double traffic = Double.parseDouble(splits[2].trim());
return new Access(time, domain, traffic);
}
});
SingleOutputStreamOperator<Tuple2<String, Double>> reduceStream = mapStream.flatMap(new FlatMapFunction<Access, Tuple2<String, Double>>() {
@Override
public void flatMap(Access value, Collector<Tuple2<String, Double>> out) throws Exception {
out.collect(Tuple2.of(value.getDomain(), value.getTraffic()));
}
}).keyBy(new KeySelector<Tuple2<String, Double>, String>() {
@Override
public String getKey(Tuple2<String, Double> value) throws Exception {
return value.f0;
}
}).reduce(new ReduceFunction<Tuple2<String, Double>>() {
@Override
public Tuple2<String, Double> reduce(Tuple2<String, Double> value1, Tuple2<String, Double> value2) throws Exception {
return Tuple2.of(value1.f0, value1.f1 + value2.f1);
}
});
FlinkJedisPoolConfig conf = new FlinkJedisPoolConfig.Builder().setHost("127.0.0.1").setPassword("123456")
.setPort(6379).build();
reduceStream.addSink(new RedisSink<Tuple2<String, Double>>(conf, new PkRedisSink()));
//reduceStream.addSink(new PkMySqlSink()); }

下面先来看Redis的Sink,这种采用的是实现RedisMapper来实现Redis的写出

public class PkRedisSink implements RedisMapper<Tuple2<String, Double>> {
@Override
public RedisCommandDescription getCommandDescription() {
return new RedisCommandDescription(RedisCommand.HSET, "pk-traffic");
} @Override
public String getKeyFromData(Tuple2<String, Double> data) {
return data.f0;
} @Override
public String getValueFromData(Tuple2<String, Double> data) {
return data.f1 + "";
}
}

但是这种方式不是特别灵活,我们一般都使用继承RichSinkFunction来进行数据的写出,因为我们可以使用它的生命周期函数,这个是非常有用的,为什么这样说呢,使用这一方法我们可以适用于非常非常多的Sink的需求,需要修改的不是很多,使用起来也会很方便

public class PkMySqlSink extends RichSinkFunction<Tuple2<String, Double>> {

    Connection connection;
PreparedStatement insertPstmt;
PreparedStatement updatePstmt; @Override
public void open(Configuration parameters) throws Exception {
super.open(parameters);
Connection connection = MySQLUtils.getConnection();
insertPstmt = connection.prepareStatement("insert into traffic(domain, traffic) values(?, ?)");
updatePstmt = connection.prepareStatement("update traffic set traffic = ? where domain = ?"); } @Override
public void close() throws Exception {
super.close();
if (null != insertPstmt) {
insertPstmt.close();
} if (null != updatePstmt) {
updatePstmt.close();
} if (null != connection) {
connection.close();
} } @Override
public void invoke(Tuple2<String, Double> value, Context context) throws Exception { System.out.println("=====invoke======" + value.f0 + "==>" +value.f1);
updatePstmt.setString(2, value.f0);
updatePstmt.setDouble(1, value.f1);
updatePstmt.execute(); if (updatePstmt.getUpdateCount() == 0) {
insertPstmt.setString(1, value.f0);
insertPstmt.setDouble(2, value.f1);
insertPstmt.execute();
} }

最后

这里就展示了两种写入Sink的方式,其他方式如果需要使用我们可以去查询官方文档,文档都有会有一个demo,大家可以根据demo改成自己需要的就可以sink出去了

flink之Sink to MySQL和Redis的更多相关文章

  1. Flink自定义Sink

    Flink自定义Sink Flink 自定义Sink,把socket数据流数据转换成对象写入到mysql存储. #创建Student类 public class Student { private i ...

  2. Flink的sink实战之四:自定义

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...

  3. linux安装和配置 mysql、redis 过程中遇到的问题记录

    linux下部署mysql和redis网上的教程很多,这里记录一下我部署.配置的过程中遇到的一些问题和解决办法. mysql ①安装完成后启动的时候报错 Starting MySQL.The serv ...

  4. Mysql与Redis的同步实践

    一.测试环境在Ubuntu kylin 14.04 64bit 已经安装Mysql.Redis.php.lib_mysqludf_json.so.Gearman. 点击这里查看测试数据库及表参考 本文 ...

  5. 通过Gearman实现MySQL到Redis的数据同步

    对于变化频率非常快的数据来说,如果还选择传统的静态缓存方式(Memocached.File System等)展示数据,可能在缓存的存取上会有很大的开销,并不能很好的满足需要,而Redis这样基于内存的 ...

  6. 一步完成 MySQL 向 Redis 迁移

    从mysql搬一个大表到redis中,你会发现在提取.转换或是载入一行数据时,速度慢的让你难以忍受.这里我就要告诉一个让你解脱的小技巧.使用“管道输出”的方式把mysql命令行产生的内容直接传递给re ...

  7. MySQL to Redis

    [TOC] 简介 使用mysql2redis可以非常便捷的将mysql中的数据导出到redis中去, 通常是需要一个select语句即可实现. 软件安装 // 安装apr + apr-util $ w ...

  8. Gearman + Nodejs + MySQL UDF异步实现 MySQL 到 Redis 的数据同步

    [TOC] 1, 环境 CentOS, MySQL, Redis, Nodejs 2, Redis简介 Redis是一个开源的K-V内存数据库,它的key可以是string/set/hash/list ...

  9. mysql常见优化,更多mysql,Redis,memcached等文章

    mysql常见优化 http://www.cnblogs.com/ggjucheng/archive/2012/11/07/2758058.html 更多mysql,Redis,memcached等文 ...

  10. linux安装和配置 mysql、redis 过程中遇到的问题记录(转)

    章节目录 mysql redis linux下部署mysql和redis网上的教程很多,这里记录一下我部署.配置的过程中遇到的一些问题和解决办法. mysql ①安装完成后启动的时候报错 Starti ...

随机推荐

  1. binom_test

    bt <- function(a, b, p = 0.5) {binom.test(a, b+a, 0.5, alternative= c("two.sided"), con ...

  2. python调用java&反编译地址

    反编译工具地址: https://github.com/java-decompiler/jd-gui/releases 你想知道的JPype全在这里∞   先总结自己趟的坑 1. python进程是6 ...

  3. Java中简单易懂的HashMap面试题(面试必备)

    这篇文章仅限小编个人的理解,小编不是Java方向的,只是对Java有很高的学习兴趣 如果有什么不对的地方还望大佬指点 HashMap的底层是数组+链表,(很多人应该都知道了) JDK1.7的是数组+链 ...

  4. mysql-开启日志记录功能

    开启日志记录功能 -- 开启功能 SET GLOBAL general_log = ON; -- 保存到文件 SET GLOBAL log_output = 'file'; 查看日志内容 -- 查看日 ...

  5. C#测试web服务是否可用(转)

    转摘:http://www.cnblogs.com/xienb/p/3443282.html winform客户端经常需要调用webservice或者WCF进行数据交互,但是远程服务有可能不存在或者服 ...

  6. 关于Electron环境配置与一些相关的错误解决

    安装步骤: 1.安装NVM: 这个是nodejs的版本管理器,github上有一个nvm for windows,由于不能的nodejs的版本问题,可以自由进行切换. 下载地址:https://git ...

  7. 总结Unity查找物体的几种方法

    Unity中经常需要查找对象,对应的API也有好几种,各自有不同的适用场合. 1. GameObject.Find 通过名字或路径查找游戏对象. GameObject.Find("GameO ...

  8. 实验1.SDN拓扑实践

    实验1:SDN拓扑实践 一.基本要求 (一)Mininet运行结果截图 (二) 使用Mininet的命令行生成如下拓扑: 1. 3台交换机,每个交换机连接1台主机,3台交换机连接成一条线. 2. 3台 ...

  9. python中的反射机制

    转自https://www.cnblogs.com/renjie1105/p/15909285.html python反射简介 在做程序开发中,我们常常会遇到这样的需求:需要执行对象里的某个方法,或需 ...

  10. 06-Spring整合mybatis实现简易登录

    1. 文件结构 pojo-Users: //属性名与数据库列名一致 public class Users implements Serializable { private int uid; priv ...