前言

下面这篇文章是使用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. Linux命令之定时调度-crontab

    以上cron命令格式为:* * * * * [root run-parts] command 前面五个*号代表时间,用数字,数字的取值范围和含义如下: 第一个*:分钟 (0-59)[整数] 第二个*: ...

  2. java获取类内容

    java获取类内容 Book类 public class Book implements Serializable { private int id; private String name; pri ...

  3. 117、商城业务---分布式事务---RabbitMQ延时队列

    1.定时任务存在的问题 即任务过期时间为30min,任务在第31min过期,但是在第60分钟才被扫描到 2.延时队列 是先设置一个过期队列,里面消息过期后不会丢弃而是通过交换机放到另一个队列中.从这个 ...

  4. 使用python来搭建一个简易的文件下载环境以及用droopy来实现一个文件上传环境

    ubuntu在安装的时候一般都是自带python环境的,大家可以查看一下查看demo如下 用于共享的命令很简单python2: python -m SimpleHTTPServer 8888pytho ...

  5. Jmeter--请求结果写入文件并生成报告

    一.数据写入文件 Jmeter中监听器控件中,都可以将"所有数据写入一个文件",且文件形式有:xml\jtl\csv 在需要写入的监听器下点击"浏览"按钮,选择 ...

  6. ArcEngine(平板电脑墨迹错误代码。多次调用 RtpEnabled (异常来自 HRESULT:0x80040239))问题未有效解决

    测试数据库中的要素无法执行ITopologicOperater接口下的方法,错误如图 暂记,错误未解决 tip: 1.随便移动一个节点 也不报错/ 2.手动按照他的节点画一个也不报错 3.bufer参 ...

  7. 【其他】etcd

    配置 node1 name: etcd-1 data-dir: /data/etcd/node1 listen-client-urls: http://127.0.0.1:6701 advertise ...

  8. 7. 基础增删改 - 创建管理员用Model-Drive App管理后台信息 - 在Model-Driven App中创建视图

    ​ 当我们创建完Model-Driven之后,就可以在里面创建我们所需要的视图,视图一般分为三类: 个人:根据自己的个人需求创建个人视图,只有创建者和其分享的人才能查看这些视图. 公共:可以根据团体需 ...

  9. 飞桨AI 文本实体抽取 数据准备(excel 文本标注)

    网纸: https://ai.baidu.com/easydl/app/deploy/tee/public #!/usr/bin/env python3 # -*- coding: utf-8 -*- ...

  10. cmd查看对应端口使用情况

    cmd查看端口号netstat -ano | findstr 80