在实际开发中,需要做数据同步的场景是非常多的,比如不同的应用之间不想直接通过RPC的方式进行数据交互,或者说下游应用需要检测来自上游应用的某些业务指标数据的变化时,这些都可以考虑使用数据同步的方式完成;
数据同步通常分为离线同步,和准实时同步,以mysql为例,当下游应用需要通过监控上游的mysql某个表的数据变化来完成自身的业务时,数据同步的实现方式可以有很多种,比如通过canal的方式在应用层做监控,这也是比较常用的一种方式;
在大数据场景下,我们可以考虑另一种方式,即Flink CDC,这也是一种比较通用的数据同步解决方案;
不管是使用哪种方式,其底层的核心原理都是通过监控mysql的binlog的日子变化,从而进行日子解析,得到变化的数据;
下面通过Flink CDC提供的2种常用的数据同步方式,演示下如何使用Flink CDC同步mysql的数据;
github配置参考地址:https://github.com/ververica/flink-cdc-connectors
1、安装mysql服务,并开启binlog;
注意,这里的: binlog_format一定要选择为 row的模式
从上面的配置可以看到,这里监控的是bank1这个数据库,为了方便后面演示,提前创建一张测试使用的表,建表sql如下:
CREATE TABLE `record` (
`id` varchar(12) DEFAULT NULL,
`name` varchar(22) DEFAULT NULL,
`version` int(12) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
导入maven依赖
org.apache.flink
flink-java
1.12.0
org.apache.flink
flink-streaming-java_2.12
1.12.0
org.apache.flink
flink-clients_2.12
1.12.0
org.apache.hadoop
hadoop-client
3.1.3
mysql
mysql-connector-java
5.1.49
com.alibaba.ververica
flink-connector-mysql-cdc
1.2.0
com.alibaba
fastjson
1.2.75
org.apache.flink
flink-table-planner-blink_2.12
1.12.0
核心代码如下,
import com.alibaba.ververica.cdc.connectors.mysql.MySQLSource;
import com.alibaba.ververica.cdc.connectors.mysql.table.StartupOptions;
import com.alibaba.ververica.cdc.debezium.DebeziumSourceFunction;
import com.alibaba.ververica.cdc.debezium.StringDebeziumDeserializationSchema;
import org.apache.flink.streaming.api.datastream.DataStreamSource;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
public class CdcTest1 {
public static void main(String[] args) throws Exception {
//1.创建执行环境
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
env.setParallelism(1);
DebeziumSourceFunction sourceFunction = MySQLSource.builder()
.hostname("MySql服务IP")
.port(3306)
.username("root")
.password("root")
.databaseList("bank1")
.tableList("bank1.record")
.startupOptions(StartupOptions.initial())
.deserializer(new StringDebeziumDeserializationSchema())
.build();
DataStreamSource streamSource = env.addSource(sourceFunction);
streamSource.print();
env.execute("flinkCdc");
}
}
运行这段代码,可以看到已经就绪,准备监控表的数据变化
然后我们再record表新增一条数据吧,可以看到,控制台立即输出了监控到的变化的数据信息
或者我们删除一条数据
核心代码如下:
import org.apache.flink.api.java.tuple.Tuple2;
import org.apache.flink.streaming.api.datastream.DataStream;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.table.api.Table;
import org.apache.flink.table.api.bridge.java.StreamTableEnvironment;
import org.apache.flink.types.Row;
public class CdcTest2 {
public static void main(String[] args) throws Exception{
//1.创建执行环境
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
env.setParallelism(1);
StreamTableEnvironment tableEnv = StreamTableEnvironment.create(env);
//2.创建 Flink-MySQL-CDC 的 Source
tableEnv.executeSql("CREATE TABLE user_info1 (" +
" id STRING NOT NULL," +
" name STRING NOT NULL," +
" version INTEGER NOT NULL" +
") WITH (" +
" 'connector' = 'mysql-cdc'," +
" 'hostname' = 'IP'," +
" 'port' = '3306'," +
" 'username' = 'root'," +
" 'password' = '123456'," +
" 'database-name' = 'bank1'," +
" 'table-name' = 'record'" +
")");
//tableEnv.executeSql("select * from user_info1").print();
Table table = tableEnv.sqlQuery("select * from user_info1");
DataStream> retractStream = tableEnv.toRetractStream(table, Row.class);
retractStream.print();
env.execute("flinkCdcSql");
}
}
简单解释下这段代码中的那段sql的含义,即通过一个sql创建一张表,这张表可以理解为一张逻辑上的表,用于检测数据库中的那张物理表 record的数据变化,当record表数据发生变化的时候,将会同步到usr_info1这张表中,那么程序就可以读取到usr_info1的数据了
启动上面的程序,观察控制台日志输出,此时可以看到,监控已经就绪,
解接下来,按照上面的同样的操作步骤,首先给数据表 record增加一条数据,可以看到,立即检测到了数据的变化
下面再删除一条数据看看,也能立即检测到删除的数据