FlinkSQL MySQL维表关联

该博客介绍了如何使用Flink SQL处理Kafka数据,包括数据清洗、维表关联以及结果数据写回Kafka。通过设置Flink环境、配置参数、定义UDF函数以及创建Kafka和MySQL的源表与Sink表,实现了从Kafka消费数据,进行MySQL维表的Temporal Join操作,并将处理后的数据重新发布到Kafka。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

需求:消费Kafka数据,进行数据清洗及维表关联补齐字段,结果数据写入Kafka。 

import java.time.Duration

import com.sm.function.udf._
import com.sm.common.conf.PropManager
import com.sm.constants.Constants
import com.sm.utils.FlinkUtils
import org.apache.flink.api.common.restartstrategy.RestartStrategies
import org.apache.flink.api.common.time.Time
import org.apache.flink.streaming.api.environment.{CheckpointConfig, ExecutionCheckpointingOptions}
import org.apache.flink.streaming.api.scala._
import org.apache.flink.streaming.api.{CheckpointingMode, TimeCharacteristic}
import org.apache.flink.table.api.bridge.scala.StreamTableEnvironment
import org.apache.log4j.Level
import org.slf4j.LoggerFactory

/**
  * flink sql 维表关联
  * 消费kafka, MySQL维表关联, 结果写入kafka
  *
  * create by LiuJinHe 2020/10/22
  */
object LoginEtlKafka2Kafka {
  private var logger: org.slf4j.Logger = _

  def main(args: Array[String]): Unit = {
    logger = LoggerFactory.getLogger(this.getClass.getSimpleName)
    org.apache.log4j.Logger.getLogger("org.apache.hadoop").setLevel(Level.WARN)
    org.apache.log4j.Logger.getLogger("org.apache").setLevel(Level.INFO)

    // 初始化 stream 环境
    // 本地测试,需要 flink-runtime-web 依赖
    //   val env = StreamExecutionEnvironment.createLocalEnvironmentWithWebUI()
    val env = StreamExecutionEnvironment.getExecutionEnvironment
    // 本地测试线程 1
    //    env.setParallelism(1)

    //    val params = ParameterTool.fromArgs(args)
    //    env.getConfig.setGlobalJobParameters(params)

    // 失败重启,固定间隔,每隔3秒重启1次,总尝试重启10次
    env.setRestartStrategy(RestartStrategies.fixedDelayRestart(10, 3))

    // 事件处理的时间,由系统时间决定
    env.setStreamTimeCharacteristic(TimeCharacteristic.ProcessingTime)

    // 创建 streamTable 环境
    val tableEnv: StreamTableEnvironment = StreamTableEnvironment.create(env, FlinkUtils.getSettings)
    //    tableConfig.setIdleStateRetentionTime(Time.hours(12), Time.hours(24))

    // checkpoint 设置
    val tableConfig = tableEnv.getConfig.getConfiguration
    tableConfig.set(ExecutionCheckpointingOptions.CHECKPOINTING_MODE, CheckpointingMode.EXACTLY_ONCE)
    // checkpoint的超时时间周期,1 分钟做一次checkpoint, 每次checkpoint 完成后 sink 才会执行
    tableConfig.set(ExecutionCheckpointingOptions.CHECKPOINTING_INTERVAL, Duration.ofSeconds(60))
    // checkpoint的超时时间, 检查点一分钟内没有完成将被丢弃
    tableConfig.set(ExecutionCheckpointingOptions.CHECKPOINTING_TIMEOUT, Duration.ofSeconds(60))
    // checkpoint 最小间隔,两个检查点之间至少间隔 30 秒
    tableConfig.set(ExecutionCheckpointingOptions.MIN_PAUSE_BETWEEN_CHECKPOINTS, Duration.ofSeconds(30))
    // 同一时间只允许进行一个检查点
    tableConfig.set(ExecutionCheckpointingOptions.MAX_CONCURRENT_CHECKPOINTS, Integer.valueOf(1))
    // 手动cancel时是否保留checkpoint
    tableConfig.set(ExecutionCheckpointingOptions.EXTERNALIZED_CHECKPOINT,
      CheckpointConfig.ExternalizedCheckpointCleanup.RETAIN_ON_CANCELLATION)

    // 设置状态的最小空闲时间和最大的空闲时间
    tableEnv.getConfig.setIdleStateRetentionTime(Time.hours(12), Time.hours(24))

    tableConfig.setString("table.exec.mini-batch.enabled", "true")
    tableConfig.setString("table.exec.mini-batch.allow-latency", "2s")
    tableConfig.setString("table.exec.mini-batch.size", "5000")
    tableConfig.setString("table.optimizer.distinct-agg.split.enabled", "true")

    // 测试
    //    val odsLoginTopic = "ods_login"
    //    val bootstrapServers = "192.168.100.39:9092&#
### FlinkSQL关联使用方法 #### MySQL 关联Flink SQL中,可以利用`Table API & SQL`以及`Flink JDBC连接器`来实现MySQL关联操作。通过定义一个带有特定选项的catalog或直接创建临时视图的方式引入外部MySQL作为参与计算[^1]。 对于简单的单字段匹配场景可以直接指定key列完成join动作;而面对复杂多键值组合的情况,则需借助字符串拼接(concat)或是自定义格函数(table function),尽管过程稍显繁琐却也提供了灵活性[^2]。 ```sql CREATE TABLE mysql_dim_table ( id BIGINT, name STRING, description STRING, PRIMARY KEY (id) NOT ENFORCED ) WITH ( 'connector' = 'jdbc', 'url' = 'jdbc:mysql://localhost:3306/testdb', 'table-name' = 'dim_table' ); -- 流Join示例 SELECT t1.order_id, t1.product_id, dim.name AS product_name FROM order_stream AS t1 LEFT JOIN mysql_dim_table FOR SYSTEM_TIME AS OF t1.proctime AS dim ON t1.product_id = dim.id; ``` #### Redis 关联优化 考虑到性能因素,在某些应用场景下选用Redis作为缓存层存储频繁访问的小型度信息不失为一种明智之举。这不仅能够加速查询效率还能减轻源端数据库的压力。不过值得注意的是当涉及到复合主键时确实存在一定的不便之处,此时可考虑采用哈希结构或其他高级特性简化处理逻辑。 #### 广播机制下的高效Join策略 为了进一步提升作业执行效能并减少网络传输开销,官方推荐针对规模较小且更新频率较低的静态采取广播分发模式实施全量复制至各个TaskManager节点本地内存之中供即时查阅引用[^4]。 ```sql -- 创建广播 CREATE TEMPORARY VIEW broadcasted_dimension AS WITH WATERMARK FOR proctime AS proctime - INTERVAL '5' SECOND SELECT * FROM kafka_source; -- 应用广播提示符进行优化后的Join语句 SELECT /*+ MAPJOIN(broadcasted_dimension) */ ... FROM stream_table LEFT JOIN broadcasted_dimension ON stream_table.key = broadcasted_dimension.key; ``` #### 时间旅行功能支持历史版本回溯 最后值得一提的是Temporal Table Function Join所提供的强大能力——允许基于事件时间戳精准定位到对应时间节点上的有效记录从而达成过去某一刻状态重现的目的,这对于审计追踪类需求尤为适用。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

訾零

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值