flink 双流join的简单demo验证(mysql --> print)

更新日志

2024-02-16
mysql侧binlog文件开启
flink cdc双流join – right join
2024-03-02
双流join – left join & inner join

前置mysql侧 开启binlog遇到的问题

风险确定:

江湖版解决办法,可能非最优解,大力出奇迹版
解的流程是,把mysql停掉,然后新建一下对应文件
会存在data文件重新创建,重要的数据需要提前备份

现象:Windows mysql主目录下无my.ini

问题原因:

在这里插入图片描述

解决办法:

1. 确认mysql服务名称

a.
在这里插入图片描述

2. 删除对应服务,重建mysql
sc delete MySQL80

c. 在这里插入图片描述

d. 在这里插入图片描述
e. 停止mysql服务(点击停止后会反馈你未安装),新建一个mysql的my.ini文件
f. 由于初始的目的是为了开启binlog,所有就单纯的增加了一些binlog文件

[mysqld]
#设置日志三种格式:STATEMENT、ROW、MIXED 。
binlog_format = mixed
#设置日志路径,注意路经需要mysql用户有权限写,这里可以写绝对路径,也可以直接写mysql-bin(后者默认就是在/var/lib/mysql目录下)
log-bin = mysql-bin
#设置binlog清理时间
expire_logs_days = 7
#binlog每个日志文件大小
max_binlog_size = 100m
#binlog缓存大小
binlog_cache_size = 4m
#最大binlog缓存大小
max_binlog_cache_size = 512m
#配置serverid
server-id=1

后续命令如下,统一代码块里面构建
g.
在这里插入图片描述

# data文件重新生成 需等待
mysqld --initialize-insecure --user=mysql

# 重新构建MySQL服务
mysqld --install "MySql80" --defaults-file="C:\\Program Files\\MySQL\\MySQL Server 8.0\\my.ini"

# 服务里面右击启动即可如代码块结束图1 也可使用命令方法,如
net start MySql80

在这里插入图片描述

3. mysql服务重新构建

h.
修改mysql登录密码 mysql -u root -p
初次登录无序密码,回车直接登录
i. 修改登录密码

ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '12345678';
4. binlog是否开启验证

在这里插入图片描述

双流Join简单描述

写在前面

Flink CDC只是单纯的使用一下哈,非原理性讲解哈,原理性的话,可以看一下雪尽老师的解释哈,个人觉得这篇应该是最好的系统化学习资料了Flink CDC 2.x设计原理 比较难理解的可能如何拉取数据,本质是select binlog语句拉取。
关于双流join更深层次的知识,有需要的同学可以看一下这个文章
这篇文章的博主从数据质量(发的数据应该是什么样子的)和数据时效性(关联到了后还是我想要的数据嘛)来讨论的,那这篇文章从另一个角度出发,各类join产生的各种结果,也会简单的描述一些适用的场景。没有最合适的join,只有适用于场景的join。
先从简单的双流join来说,inner join ,right join,left join

代码构建

双流join 纯SQL版
import org.apache.flink.configuration.Configuration;
import org.apache.flink.configuration.RestOptions;
import org.apache.flink.table.api.EnvironmentSettings;
import org.apache.flink.table.api.Table;
import org.apache.flink.table.api.TableEnvironment;

import static org.apache.flink.table.api.Expressions.$;

/**
 * @author 划水小苏
 * @date 2024/02/16 19:30
 * @target:
 **/
public class TestDemo02 {
    public static void main(String[] args) {
        //1.使用本地模式
        Configuration conf = new Configuration();
        //设置WebUI绑定的本地端口
        conf.setString(RestOptions.BIND_PORT,"8081");
        // https://nightlies.apache.org/flink/flink-docs-release-1.13/zh/docs/dev/table/config/
        // 并行度设置
        conf.setString("table.exec.resource.default-parallelism","1");
        // pipeline.operator-chaining 拆分算子
        conf.setString("pipeline.operator-chaining","false");
        EnvironmentSettings settings = EnvironmentSettings
                .newInstance()
                .inStreamingMode()
                .withConfiguration(conf)
                .build();
        TableEnvironment tabelEnv = TableEnvironment.create(settings);

        tabelEnv.executeSql("CREATE TABLE test01 (\n" +
                "    `a1` VARCHAR(25) ,\n" +
                "    `a2` VARCHAR(25) NOT NULL,\n" +
                "    PRIMARY KEY (a2) NOT ENFORCED \n" +
                ") WITH (\n" +
                "'connector' = 'mysql-cdc', \n"+
                "'database-name' = 'sk_db_test01',  \n"+
                "'hostname' = '127.0.0.1', \n"+
                "'password' = '12345678', \n"+
                "'port' = '3306', \n"+
                "'table-name' = 'test01', \n"+
                "'username' = 'root', \n"+
                "'scan.startup.mode' = 'latest-offset' \n"+
                ")");

        tabelEnv.executeSql("CREATE TABLE test02 (\n" +
                "    `b1` VARCHAR(25) ,\n" +
                "    `b2` VARCHAR(25) NOT NULL,\n" +
                "    PRIMARY KEY (b2) NOT ENFORCED \n" +
                ") WITH (\n" +
                "'connector' = 'mysql-cdc', \n"+
                "'database-name' = 'sk_db_test01',  \n"+
                "'hostname' = '127.0.0.1', \n"+
                "'password' = '12345678', \n"+
                "'port' = '3306', \n"+
                "'table-name' = 'test02', \n"+
                "'username' = 'root', \n"+
                "'scan.startup.mode' = 'latest-offset' \n"+
                ")");

        tabelEnv.executeSql("CREATE TABLE PrintSink (\n" +
                "    `c1` VARCHAR(25), \n" +
                "    `c2` VARCHAR(25), \n" +
                "    `c3` VARCHAR(25)  \n" +
                ") WITH (\n" +
                "   'connector'  = 'print' \n" +
                ")");
        tabelEnv.executeSql("INSERT INTO PrintSink\n" +
                "SELECT a.*,b.b1 FROM test01 AS a\n" +
                "RIGHT join test02 AS b\n" +
                "ON a.a2 = b.b2\n" +
                ";");
    }
}

pom 文件 (新增mysql connector依赖)

完整版看Flink table api那个pom哈,新增即可

<!--        mysql cdc 相关依赖-->
        <dependency>
            <groupId>org.apache.flink</groupId>
            <artifactId>flink-connector-base</artifactId>
            <version>${flink.version}</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.ververica/flink-connector-mysql-cdc -->
        <dependency>
            <groupId>com.ververica</groupId>
            <artifactId>flink-connector-mysql-cdc</artifactId>
            <version>2.3.0</version>
<!--            <scope>provided</scope>-->
        </dependency>
mysql侧sql
-- 建表
DROP TABLE IF EXISTS `test01` ;
CREATE TABLE test01 (
  `a1` VARCHAR(25),
  `a2` VARCHAR(25) NOT NULL,
  PRIMARY KEY (a2)
);

DROP TABLE IF EXISTS `test02` ;
CREATE TABLE test02 (
  `b1` VARCHAR(25),
  `b2` VARCHAR(25) NOT NULL,
  PRIMARY KEY (b2)
);

-- 数据插入与更新
INSERT INTO `test01` values("左1","sk01");
SELECT * FROM `test01` ;
UPDATE `test01`  set `a1` = "左2"  where `a2` = "sk01";

INSERT INTO `test01` values("左1","sk02");

INSERT INTO `test02` values("右1","sk01");
SELECT * FROM `test02` ;
UPDATE `test02`  set `b1` = "右2"  where `b2` = "sk01";

right join

简单概述

首先进行一个简单的排列组合一下,左流数据有或无,右流数据有或无,展开即为
(有,无) | (有,有) | (无,无) | (无,有)
第三种不在简述里面存在,那就丢掉这种可能,只讨论剩下的三种情况

-- 右流来了数据,左流没这种数据怎么办?
+I[null,b]
-- 那后面左流来了这条数据呢?
-D[null,b]
+I[a,b]
-- 存在一个疑问点就是这个右流的数据是什么情况,为什么还有-D这种?
未关联到数据,不会立即丢弃掉,而是存在记忆里面,但是记忆存多久呢?State的ttl就是记忆时间
在记忆时间里面,左流数据到达后,会重新下发数据,也就常说的回撤。
关于-D操作是因为在实时计算里面,这种动态表概念,详情可以看官网详解哈,这里通过白话来理解哈,
在整体的流计算数据里面,由于存在一些记忆,
让flink理解到之前的数据是脏数据,需要使用-D来把之前的+I数据抵消掉,从而下发一条新的数据
但,至于sink端如何处理这些数据,是依次+I还是进行+U是由sink端处理的,flink侧只负责下发这种逻辑

-- 右流来了数据,关联到左流的数据会下发什么?
+I[a,b]
-- 如果左流不断更新,数据会下发什么?
+I[a1,b]
-D[a1,b]
+I[a2,b]
在记忆时间里面,会一直维护条数据,会出现不断更新
-- 如果左流来了数据,但是右流没数据关联,数据下发会是什么样子呢
示例:

基于阿里云实现结果的截图,上面的demo控制台也是可以一样输出的,强烈推荐阿里云Flink产品,我觉得很nice,最起码写sql很得劲,我是一个快乐的sql boy。
在这里插入图片描述

1、新增右流数据

INSERT INTO test02 values(“右1”,“sk01”);

在这里插入图片描述

2、新增左流数据

INSERT INTO test02 values(“右1”,“sk01”);

在这里插入图片描述

3、更新左流数据

UPDATE test01 set a1 = “左2” where a2 = “sk01”;

在这里插入图片描述

4、更新右流数据

UPDATE test02 set b1 = “右2” where b2 = “sk01”;

在这里插入图片描述

left join

简单概述

基于上续Java代码只修改right 为 left 即可

在这里插入图片描述

简单概述现象
左不等右等 左2右4

示例

1、先来左流数据 ( INSERT INTO test01 values(“左1”,“sk01”); )

+I [左1, sk01, null]

在这里插入图片描述
2、先来右流数据( INSERT INTO test02 values(“右1”,“sk01”); )

无数据输出 (相当于首次执行哈,要和上面的顺序执行做区分)

3、join之后的情况

+I [左1, sk01, 右1]

image-20240302154752750
4、更新左流数据 ( UPDATE test01 set a1 = “左2” where a2 = “sk01”; )

-D [左1, sk01, 右1]
+I [左2, sk01, 右1]

image-20240302154953640

5、更新右流数据 ( UPDATE test02 set b1 = “右2” where b2 = “sk01”; )

-U [左2, sk01, 右1]
+I [左2, sk01, null]
-D [左2, sk01, null]
+I [左2, sk01, 右2]

image-20240302155044995

inner join

简单概述

左右都会等数据,等不到数据不发,ttl过期数据则丢失

示例

此时 无论先输入拿一条insert数据,都不会存在数据下发情况 双insert才会下发数据。
1、sql输入语句

INSERT INTO test01 values(“左1”,“sk01”);
INSERT INTO test02 values(“右1”,“sk01”);

+I [左1, sk01, 右1]

在这里插入图片描述

2、左流更新

UPDATE test01 set a1 = “左2” where a2 = “sk01”;
-U [左1, sk01, 右1]
+U [左2, sk01, 右1]

在这里插入图片描述
3、右流更新

UPDATE test02 set b1 = “右2” where b2 = “sk01”;
-U [左2, sk01, 右1]
+U [左2, sk01, 右2]

在这里插入图片描述

  • 12
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值