FlinkSql-Mysql

flink SQL 将msyql当做数据源

  1. 阿里耙耙开源的flink-mysql-conn-cdc:https://github.com/ververica/flink-cdc-connectors
  2. 原理:获取mysql增删改查所产生的日志信息binlog,将二进制binlog数据(StringDebeziumDeserializationSchema)反序列化转化成kafka-Debezium-JSON
  3. 代码示例:此程序为mysql Binlog日志的获取
    package conn;
    
    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.api.common.restartstrategy.RestartStrategies;
    import org.apache.flink.runtime.state.filesystem.FsStateBackend;
    import org.apache.flink.streaming.api.CheckpointingMode;
    import org.apache.flink.streaming.api.datastream.DataStreamSource;
    import org.apache.flink.streaming.api.datastream.SingleOutputStreamOperator;
    import org.apache.flink.streaming.api.environment.CheckpointConfig;
    import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
    
    import java.util.Properties;
    
    
    public class FlinkConnectorMysqlCDCDemo {
        private static Properties properties;
    
        public static void main(String[] args) throws Exception {
            //TODO 1.获取流处理执行环境
            StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
            env.setParallelism(1);
            //1.1Checkpoint相关
            /*读取的是binlog中的数据,如果集群挂掉,尽量能实现断点续传功能。如果从最新的读取(丢数据)。如果从最开始读(重复数据)。理想状态:读取binlog中的数据读一行,保存一次读取到的(读取到的行)位置信息。而flink中读取行位置信息保存在Checkpoint中。使用Checkpoint可以把flink中读取(按行)的位置信息保存在Checkpoint中*/
            env.enableCheckpointing(5000L);//5s执行一次Checkpoint
            //设置Checkpoint的模式:精准一次
            env.getCheckpointConfig().setCheckpointingMode(CheckpointingMode.EXACTLY_ONCE);
            //任务挂掉的时候是否清理checkpoint。使任务正常退出时不删除CK内容,有助于任务恢复。默认的是取消的时候清空checkpoint中的数据。RETAIN_ON_CANCELLATION表示取消任务的时候,保存最后一次的checkpoint。便于任务的重启和恢复,正常情况下都使用RETAIN
            env.getCheckpointConfig().enableExternalizedCheckpoints(CheckpointConfig.ExternalizedCheckpointCleanup.RETAIN_ON_CANCELLATION);
            //设置一个重启策略:默认的固定延时重启次数,重启的次数是Integer的最大值,重启的间隔是1s
            env.setRestartStrategy(RestartStrategies.fixedDelayRestart(3, 2000L));
            //设置一个状态后端 jobManager。如果使用的yarn集群模式,jobManager随着任务的生成而生成,任务挂了jobManager就没了。因此需要启动一个状态后端。只要设置checkpoint,尽量就设置一个状态后端。保存在各个节点都能读取的位置:hdfs中
    //        env.setStateBackend(new FsStateBackend("hdfs://hadoop102:8020/flink/ck/"));
            //指定用户
    //        System.setProperty("HADOOP_USER_NAME", "atguigu");
    
    
    
            //TODO 2.读取mysql变化数据 监控MySQL中变化的数据
            Properties properties = new Properties(); //创建一个变量可以添加之后想添加的配置信息
            DebeziumSourceFunction sourceFunction = MySQLSource.builder() //使用builder创建MySQLsource对象,需要指定对象的泛型。
                    .hostname("127.0.0.1") //指定监控的哪台服务器(MySQL安装的位置)
                    .port(3306) //MySQL连接的端口号
                    .username("root") //用户
                    .password("123456")//密码
                    .databaseList("xxxx") //list:可以监控多个库
                    .tableList("xxx.xxxx") //如果不写则监控库下的所有表,需要使用【库名.表名】
                    .serverId(9999)
                    //.debeziumProperties(properties)//debezium中有很多配置信息。可以创建一个对象来接收
                    .deserializer(new StringDebeziumDeserializationSchema()) //读的数据是binlog文件,反序列化器,解析数据
                    .startupOptions(StartupOptions.initial()) //初始化数据:空值读不读数据库中的历史数据。initial(历史+连接之后的)、latest-offset(连接之后的)。timestamp(根据指定时间戳作为开始读取的位置)
                    .build();
    
            env
                    .addSource(sourceFunction)
                    .print().setParallelism(1);
    
            //TODO 4.启动任务
            env.execute();
        }
    }
    
  4. mysql数据的获取:值得注意点是flink1.10后将tEnv.sqlUpdate抛弃,更换为executeSql(table_name),进行sql表的创建sqlQuery(table_name)为sql增删改的执行

    package conn;
    
    import org.apache.flink.api.java.utils.ParameterTool;
    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 source_mysql {
        public static void main(String[] args) throws Exception {
            final ParameterTool params = ParameterTool.fromArgs(args);
            final StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
            env.setParallelism(1); // source only supports parallelism of 1
            final StreamTableEnvironment tEnv = StreamTableEnvironment.create(env);
            String SOURCE_MYSQL=
                    "CREATE TABLE mysql_ssp_slot(\n"+
                            "id STRING,\n"+
                            "name STRING,\n"+
                            "name2 STRING,\n"+
                            "name3 STRING\n"+
                            ")WITH (\n"+
                            "'connector' = 'mysql-cdc',\n"+
                            "'hostname' = '127.0.0.1',\n"+
                            "'port' = '3306',\n"+
                            "'username' = 'root',\n"+
                            "'password' = '123456',\n"+
                            "'database-name' = 'xxx',\n"+
                            "'table-name' = 'xxxx',\n"+
                            "'debezium.snapshot.mode' = 'initial'\n"+
                            ")\n";
            tEnv.executeSql(SOURCE_MYSQL);
            String selectSql = "SELECT * FROM mysql_ssp_slot ";
            final Table result = tEnv.sqlQuery(selectSql);
            tEnv.toRetractStream(result,Row.class).print();
            env.execute();
        }
    }
    

     

  5. 即将更新:source-mysql动态数据,sink到kafka/clickhosue/mysql,思路cdc结合jdbc

  6. 记录一点感悟:flinksql是将数据均读取到代码中创建的create表,所有的查询语句基于create表进行查询,最后要保证有输出源,当输出源存在的时候,将不需要env.execute()

异常处理

  1. Could not find a suitable table factory for 'org.apache.flink.table.factories.TableSinkFactory'
    处理:代码的问题,一定要按照官网参照写:https://ci.apache.org/projects/flink/flink-docs-release-1.10/dev/table/connect.html#csv-format
    一定是connector.type等等书写有误
  2. clussNotFunction:
    1、pom文件flink版本和依赖版本是否相同
    2、需要到idea->File->Project Structure->勾选需要的依赖包
    FlinkSql-Mysql_第1张图片
  3. The server time zone value 'Öйú±ê׼ʱ¼ä' is unrec
    mysql时区的问题1、查看时区:show VARIABLES like '%time_zone%';
    FlinkSql-Mysql_第2张图片
    2、更改时区为UTC或者+08:00(多出在win系统):set global time_zone = '+8:00';
  4. org.apache.flink.table.api.TableColumn.isGenerated()Z
  5. docker版mysql开启binlog权限
    show variables like 'log_bin';
    echo -e '[mysqld]\npid-file\t= /var/run/mysqld/mysqld.pid\nsocket\t= /var/run/mysqld/mysqld.sock\ndatadir\t= /var/lib/mysql\nsymbolic-links=0\nserver-id = 1\nlog-bin = binlog\nlog-bin-index = binlog.index'>mysqld.cnf

你可能感兴趣的:(知识点,Flink,SQL,Flink,Stream,flink)