前言

下面这篇文章是使用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. 如何快速开发一套cesium三维系统

    首先我们需要明确我们做的三维应该具有哪些功能,常见的三维系统主要用于展示三维数据,常见的功能应该有,缩放平移,漫游浏览,定位,量测,图层控制等基础功能.在这些基础功能上根据业务需要,再继续扩展,添加一 ...

  2. day47-Mysql初识

    1.数据库的演变过程-- 文件存储(不同用户之间数据格式不一致,杂乱)==> 软件开发目录规范(限定了储存的具体位置,不能网络通信)==>数据库 数据库就是一款基于网络通信操作文件的应用程 ...

  3. 制作带curl命令的容器

    创建一个容器,启动后使用curl命令请求指定的地址 方法一.固定的地址,创建Dockerfile前先修改entrypoint.sh里的地址 vi entrypoint.sh#! /bin/bashcu ...

  4. weblogic11g打补丁,应用出现乱码

    解决办法: 1.找到域下的这个路径:autodeploy\manager\WEB-INF里的web.xml文件,先备份好,再添加以下语句: <context-param> <para ...

  5. Java基础学习——Arrays类

    1.数组复制 Arrays.copyOfRange(original, from, to) 此方法与System.arraycopy类似. 不同的是System.arraycopy需要提前声明目标数组 ...

  6. 从XXE漏洞修复引起Not supported: http://javax.xml.XMLConstants/property/accessExternalDTD说到SPI机制

    引子  在使用Fortify扫描时代码报XML External Entity Injection,此漏洞为xml实体注入漏洞,XXE攻击可利用在处理时动态构建文档的 XML 功能.修复方案也包含了增 ...

  7. linux使用iperf3测试带宽

    1. https://www.alibabacloud.com/help/zh/express-connect/latest/test-the-performance-of-an-express-co ...

  8. vlan概述

    一.vlan是什么? vlan顾名思义就是虚拟局域网Virtual Local Area Network,为什么要划分vlan?划分vlan可以控制广播,增强网络安全性,简化网络管理. 二.vlan的 ...

  9. 基于leaflet地图可视化(一)

    最近,在学习地图可视化是基于公司的项目.但公司在项目上居然用图片来代替.无语~~~项目效果图(第一版)如下: 突发奇想,2016年自己就接触过地图可视化.但那是没有深入研究.只会用R语言来实现点基础. ...

  10. SpringBoot笔记--事件监听+启动流程+监控+项目部署

    事件监听 ApplicationContextInitializer SpringApplicationRunListener ApplicationRunner CommandLineRunner ...