基于 Flink 实现解决数据库分库分表任务拆分

本文涉及的产品
实时计算 Flink 版,5000CU*H 3个月
简介: 基于 Flink 实现解决数据库分库分表任务拆分

1、场景描述


例如订单库进行了分库分表,其示例如下图所示:

e01363e4e52f4ae4ad54ab577cfc004f.png

现在的需求是希望创建一个任务就将数据同步到MQ集群,而不是为每一个数据库实例单独创建一个任务,将其数据导入到MQ集群,因为同步任务除了库不同之外,表的结构、数据映射规则都是一致的。


2、flinkx 的解决方案详解


2.1 fink Stream API 开发基本流程


使用 Flink Stream API 编程的通用步骤如下图所示:


18a0f132917828f59f1e9985691f1c4a.png

温馨提示:有关 Stream API 的详细内容将在后续的文章中展开,本文主要是关注 InputFormatSourceFunction,重点关注数据源的拆分。


2.2 flinkx Reader(数据源)核心类图


c2afa1885a0febbaced8e382666a0292.png

在 flinkx 中将不同的数据源封装成一个个 Reader,其基类为 BaseDataReader,上图中主要罗列了如下几个关键的类体系:


  • InputFormat
    flink 核心API,主要是对输入源进行数据切分、读取数据的抽象,其核心接口说明如下:
  • void configure(Configuration parameters)
    对输入源进行额外的配置,该方法在 Input 的生命周期中只需调用一次。
    BaseStatistics getStatistics(BaseStatistics cachedStatistics)
    返回 input 的统计数据,如果不需要统计,在实现的时候可以直接返回 null。
    T[] createInputSplits(int minNumSplits)
    对输入数据进行数据切片,使之支持并行处理,数据切片相关类体系见:InputSplit。
    InputSplitAssigner getInputSplitAssigner(T[] inputSplits)
    获取 InputSplit 分配器,主要是在具体执行任务时如何获取下一个 InputSplit,其声明如下图所示:
    101a1966b41febe194bf72aa95237f89.png

void open(T split)

根据指定的数据分片 (InputSplit) 打开数据通道。为了加深对该方法的理解,下面看一下 Flinkx 关于 jdbc、es 的写入示例:


da253530e78dc52f0434ea62d15f4b5f.png

  • boolean reachedEnd()
    数据是否已结束,在 Flink 中通常 InputFormat 的数据源通常表示有界数据 (DataSet)。
  • OT nextRecord(OT reuse)
    从通道中获取下一条记录。
  • void close()
    关闭。
  • InputSplit
    数据分片根接口,只定义了如下方法:
  • int getSplitNumber()
    获取当前分片所在所有分片中的序号。
    本文先简单介绍一下其通用实现子类:GenericInputSplit。
  • int partitionNumber
    当前 split 所在的序号
  • int totalNumberOfPartitions
    总分片数
    为了方便理解我们可以思考一下如下场景,对于一个数据量超过千万级别的表,在进行数据切分时可以考虑使用10个线程,即切割成 10分,那每一个数据线程查询数据时可以 id % totalNumberOfPartitions = partitionNumber,进行数据读取。
  • SourceFunction
    Flink 源的抽象定义。
  • RichFunction
    富函数,定义了生命周期、可获取运行时环境上下文。
  • ParallelSourceFunction
    支持并行的 source function。
  • RichParallelSourceFunction
    并行的富函数
  • InputFormatSourceFunction
    Flink 默认提供的 RichParallelSourceFunction 实现类,可以当成是RichParallelSourceFunction 的通用写法,其内部的数据读取逻辑由 InputFormat 实现。
  • BaseDataReader
    flinkx 数据读取基类,在 flinkx 中将所有的数据读取源封装成 Reader 。


2.3 flinkx Reader构建 DataStream 流程


经过了上面类图的梳理,大家应该 flink 中提到的上述类的含义有了一个大概的理解,但如何运用呢?接下来将通过查阅 flinkx 的 DistributedJdbcDataReader(BaseDataReader的子类)的 readData 调用流程,体会一下其使用方法。

3125d56092bd541e793476bc81facdfb.png

基本遵循创建 InputFormat、从而创建对应的 SourceFunction,然后通过 StreamExecutionEnvironment 的 addSource 方法将 SourceFunction 创建对应的 DataStreamSource。


2.4 flinkx 针对数据库分库分表任务拆分解决方案


正如本文开头部分的场景描述那样,某订单系统被设计成4库8表,每一个库(Schema)中包含2个表,如何提高数据导出的性能呢,如何提高数据的抽取性能呢?通常的解决方案如下:


  1. 首先按库按表进行拆分,即4库8表,可以进行切分8份,每一个数据分配处理一个实例中的1个表。
  2. 单个表的数据抽取再进行拆分,例如按ID进行取模进一步分解。


flinkx 就是采取上面的策略,我们来看一下其具体做法。


f20cc2fcc035efe4ae15a54f268fd527.png

Step1:首先先根据数据库实例、表进行拆分,按表维度组织成一个 DataSource 列表,后续将基于这个原始数据执行拆分算法。


接下来具体的任务拆分在 InputFormat 中实现,本实例在 DistributedJdbcInputFormat 的 createInputSplitsInternal 中。

5e5596b8e22506e40eb842bb5b499d3b.png


Step2:根据分区创建 inputSplit 数组,这里分区的概念就相当于上文提到方案中的第一条。

268a74b66800d47df782d8bf3889fcfb.png

Step3:如果指定了 splitKey 的任务拆分算法,首先 DistributedJdbcInputSplit 继承自 GenericInputSplit,总分区数为 numPartitions,然后生成数据库的参数,这里主要是生成 SQL Where 语句中的 splitKey mod totalNumberOfPartitions = partitionNumber,其中 splitKey 为分片键,例如 id,而 totalNumberOfPartitions 表示分区总数,partitionNumber 表示当前分片的序号,通过 SQL 取模函数进行数据拆分。

0876316644a7c2cc12c24423f4b6fbd1.png

Step4:如果未指定表级别的数据拆分键,则拆分策略是对 sourceList 进行拆分,即一些分区处理其中几个表。


关于 flinkx 中关于任务切分的介绍就到这里了。


3、总结


本文主要是基于 flinkx 介绍 MySQL 分库分表情况下如何基于 flink 进行任务切分,简单介绍了 Flink 中关于基本的编程范式、InputFormat、SourceFunction 的基本类体系。


温馨提示:本文并没有太详细对 Flink API 进行深入研究,后续会单独对 Flink 内容进行逐一剖析,但 Flink 系列的文章组织,其文章的组织并不具备顺序性,笔者会在不断实践 Flink 的过程中对 FLink 进行剖析。

相关实践学习
基于Hologres轻松玩转一站式实时仓库
本场景介绍如何利用阿里云MaxCompute、实时计算Flink和交互式分析服务Hologres开发离线、实时数据融合分析的数据大屏应用。
Linux入门到精通
本套课程是从入门开始的Linux学习课程,适合初学者阅读。由浅入深案例丰富,通俗易懂。主要涉及基础的系统操作以及工作中常用的各种服务软件的应用、部署和优化。即使是零基础的学员,只要能够坚持把所有章节都学完,也一定会受益匪浅。
相关文章
|
3月前
|
存储 数据处理 Apache
超越传统数据库:揭秘Flink状态机制,让你的数据处理效率飞升!
【8月更文挑战第26天】Apache Flink 在流处理领域以其高效实时的数据处理能力脱颖而出,其核心特色之一便是状态管理机制。不同于传统数据库依靠持久化存储及 ACID 事务确保数据一致性和可靠性,Flink 利用内存中的状态管理和分布式数据流模型实现了低延迟处理。Flink 的状态分为键控状态与非键控状态,前者依据数据键值进行状态维护,适用于键值对数据处理;后者与算子实例关联,用于所有输入数据共享的状态场景。通过 checkpointing 机制,Flink 在保障状态一致性的同时,提供了更适合流处理场景的轻量级解决方案。
57 0
|
10天前
|
消息中间件 资源调度 关系型数据库
如何在Flink on YARN环境中配置Debezium CDC 3.0,以实现实时捕获数据库变更事件并将其传输到Flink进行处理
本文介绍了如何在Flink on YARN环境中配置Debezium CDC 3.0,以实现实时捕获数据库变更事件并将其传输到Flink进行处理。主要内容包括安装Debezium、配置Kafka Connect、创建Flink任务以及启动任务的具体步骤,为构建实时数据管道提供了详细指导。
32 9
|
9天前
|
缓存 NoSQL 数据库
运用云数据库 Tair 构建缓存为应用提速,完成任务得苹果音响、充电套装等好礼!
本活动将带大家了解云数据库 Tair(兼容 Redis),通过体验构建缓存以提速应用,完成任务,即可领取罗马仕安卓充电套装,限量1000个,先到先得。邀请好友共同参与活动,还可赢取苹果 HomePod mini、小米蓝牙耳机等精美好礼!
|
2月前
|
存储 SQL 关系型数据库
一篇文章搞懂MySQL的分库分表,从拆分场景、目标评估、拆分方案、不停机迁移、一致性补偿等方面详细阐述MySQL数据库的分库分表方案
MySQL如何进行分库分表、数据迁移?从相关概念、使用场景、拆分方式、分表字段选择、数据一致性校验等角度阐述MySQL数据库的分库分表方案。
397 15
一篇文章搞懂MySQL的分库分表,从拆分场景、目标评估、拆分方案、不停机迁移、一致性补偿等方面详细阐述MySQL数据库的分库分表方案
|
1月前
|
Java Shell Maven
Flink-11 Flink Java 3分钟上手 打包Flink 提交任务至服务器执行 JobSubmit Maven打包Ja配置 maven-shade-plugin
Flink-11 Flink Java 3分钟上手 打包Flink 提交任务至服务器执行 JobSubmit Maven打包Ja配置 maven-shade-plugin
101 4
|
1月前
|
资源调度 分布式计算 大数据
大数据-111 Flink 安装部署 YARN部署模式 FlinkYARN模式申请资源、提交任务
大数据-111 Flink 安装部署 YARN部署模式 FlinkYARN模式申请资源、提交任务
89 0
|
3月前
|
资源调度 Kubernetes 调度
Flink 细粒度资源管理问题之Flink 中拆分作业如何解决
Flink 细粒度资源管理问题之Flink 中拆分作业如何解决
|
3月前
|
监控 Cloud Native 流计算
实时计算 Flink版产品使用问题之如何查看和管理任务
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStream API、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。
|
3月前
|
资源调度 Java Scala
实时计算 Flink版产品使用问题之如何实现ZooKeeper抖动导致任务失败时,能从最近的检查点重新启动任务
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStream API、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。