flink之Sink to MySQL和Redis
前言
下面这篇文章是使用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的更多相关文章
- Flink自定义Sink
		Flink自定义Sink Flink 自定义Sink,把socket数据流数据转换成对象写入到mysql存储. #创建Student类 public class Student { private i ... 
- Flink的sink实战之四:自定义
		欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ... 
- linux安装和配置 mysql、redis 过程中遇到的问题记录
		linux下部署mysql和redis网上的教程很多,这里记录一下我部署.配置的过程中遇到的一些问题和解决办法. mysql ①安装完成后启动的时候报错 Starting MySQL.The serv ... 
- Mysql与Redis的同步实践
		一.测试环境在Ubuntu kylin 14.04 64bit 已经安装Mysql.Redis.php.lib_mysqludf_json.so.Gearman. 点击这里查看测试数据库及表参考 本文 ... 
- 通过Gearman实现MySQL到Redis的数据同步
		对于变化频率非常快的数据来说,如果还选择传统的静态缓存方式(Memocached.File System等)展示数据,可能在缓存的存取上会有很大的开销,并不能很好的满足需要,而Redis这样基于内存的 ... 
- 一步完成 MySQL 向 Redis 迁移
		从mysql搬一个大表到redis中,你会发现在提取.转换或是载入一行数据时,速度慢的让你难以忍受.这里我就要告诉一个让你解脱的小技巧.使用“管道输出”的方式把mysql命令行产生的内容直接传递给re ... 
- MySQL to Redis
		[TOC] 简介 使用mysql2redis可以非常便捷的将mysql中的数据导出到redis中去, 通常是需要一个select语句即可实现. 软件安装 // 安装apr + apr-util $ w ... 
- Gearman + Nodejs + MySQL UDF异步实现 MySQL 到 Redis 的数据同步
		[TOC] 1, 环境 CentOS, MySQL, Redis, Nodejs 2, Redis简介 Redis是一个开源的K-V内存数据库,它的key可以是string/set/hash/list ... 
- mysql常见优化,更多mysql,Redis,memcached等文章
		mysql常见优化 http://www.cnblogs.com/ggjucheng/archive/2012/11/07/2758058.html 更多mysql,Redis,memcached等文 ... 
- linux安装和配置 mysql、redis 过程中遇到的问题记录(转)
		章节目录 mysql redis linux下部署mysql和redis网上的教程很多,这里记录一下我部署.配置的过程中遇到的一些问题和解决办法. mysql ①安装完成后启动的时候报错 Starti ... 
随机推荐
- Java中简单易懂的HashMap面试题(面试必备)
			这篇文章仅限小编个人的理解,小编不是Java方向的,只是对Java有很高的学习兴趣 如果有什么不对的地方还望大佬指点 HashMap的底层是数组+链表,(很多人应该都知道了) JDK1.7的是数组+链 ... 
- PyQt5高级窗口组件
			https://blog.csdn.net/A642960662/article/details/123093350?utm_medium=distribute.pc_aggpage_search_r ... 
- virsh虚拟机使用网桥来实现上网
			使用virsh-install安装虚拟机后,虚拟机不可以上网 第一步:主机上配置网桥 cp ifcfg-eno16777736 /tmp/ cp ifcfg-eno16777736 ifcfg ... 
- 【BUUCTF】ACTF2020 新生赛Include1 write up
			查看源代码+抓包都没有发现什么信息,只有这两个东东 <meta charset="utf8"> Can you find out the flag? <meta ... 
- Javaweb学习笔记第十四弹---对于Cookie和Filter的学习
			Apache Tomcat - Tomcat Native Downloads 会话追踪技术 会话:打开浏览器,建立连接,直到一方断开连接,会话才会结束:在一次会议中,可以有多次请求. 会话追踪:在多 ... 
- 使用python-gitlab获取本地gitlab仓库project信息的方法
			代码中有注释,直接看代码 #coding:utf8 #!/usr/bin/env python #@author: 9527 import gitlab import openpyxl import ... 
- CSS必知必会
			CSS概念 css的使用是让网页具有统一美观的页面,css层叠样式表,简称样式表,文件后缀名.css css的规则由两部分构成:选择器以及一条或者多条声明 选择器:通常是需要改变的HTML元素 声明: ... 
- springboot格式化timestamp时间
			spring.jackson.date-format=yyyy-MM-dd HH:mm:ss 
- Kafka 管理【主题、分区、消费者组】
			更多内容,前往 IT-BLOG 主题操作 使用 kafka-topics.sh 工具可以执行主题的大部分操作.可以用它创建.修改.删除和查看集群里的主题.要使用该工具的全部功能,需要通过 --zook ... 
- Java 面试——Zookeeper
			一.Zookeeper 实现机制 文件系统 + 通知机制 二.Zookeeper 高可用实现原理 一个 ZooKeeper 集群如果要对外提供可用的服务,那么集群中必须要有过半的机器正常工作并且彼此之 ... 
