Flink CDC如何保障数据的一致性

Flink CDC如何保障数据的一致性

前言

在大规模流处理中,故障是无可避免的。机器会宕机,网络会抖动。一个可靠的流处理引擎不仅要能高效地处理数据,更要在遇到这些故障时,保证计算结果的正确性。Apache Flink 正是因其强大的容错机制一致性保障而闻名。

本文将深入探讨 Flink 如何实现其核心的精确一次(Exactly-Once) 状态一致性,并分析在与外部系统交互时,如何结合幂等性来实现端到端的精确一次语义。


一、从最多一次到精确一次

在流处理中,我们通常关心三种一致性语义:

  • At-Most-Once(最多一次): 消息可能丢失,但绝不会重复处理。
  • At-Least-Once(至少一次): 消息可能重复处理,但绝不会丢失。
  • Exactly-Once(精确一次): 消息肯定被处理且只被处理一次,仿佛故障从未发生。

Flink 的核心优势在于其原生支持了状态层面的精确一次语义。这意味着 Flink 内部维护的计数器、窗口状态或用户自定义状态在故障恢复后都能保持绝对正确。


二、 分布式快照cp

Flink 实现精确一次的核心机制是基于 Chandy-Lamport 分布式快照算法的 检查点(Checkpoint)

1. 什么是 checkpoint?

Checkpoint 是 Flink 应用在某个时间点的全局一致性快照,它包含了:

  • 所有算子(Operator)的状态(如 sum() 的累加值)。
  • 所有数据源(Source)的读取位置(如 Kafka 的 Offset)。
  • 所有正在传输中的数据记录

这个快照会被持久化到一个可靠的分布式存储系统(如 HDFS、S3)中。

2. 核心原理:屏障(Barrier)

JobManager(主节点)会定期触发 Checkpoint。它向所有 Source 算子发送一个特殊的标记,称为 Checkpoint Barrier

  • 广播与对齐: Source 算子收到 Barrier 后,会立即快照自己的状态(记录当前 Offset),然后将 Barrier 广播给下游所有算子。下游算子需要收到所有输入流的 Barrier 后,才会对自己的状态做快照。这个“等待所有 Barrier 到达”的过程称为对齐,它是实现精确一次的关键。
  • 异步快照: 状态快照是异步执行的,这意味着算子在做快照时,仍然可以处理数据,几乎不影响性能。
  • 确认完成: 每个算子完成自己的快照后,会向 JobManager 发送确认(Ack)。当所有算子都确认后,这次 Checkpoint 才被视为全局完成。

3. 故障恢复:时光倒流

当发生故障时(如某个 TaskManager 宕机),Flink 的容错机制会自动执行:

  1. 自动检测: JobManager 检测到故障,暂停整个作业。
  2. 状态回滚: JobManager 找到最近一次成功的 Checkpoint
  3. 重新部署: 重启整个作业拓扑,并将所有算子的状态重置到 Checkpoint 记录的那个时间点。
  4. 重置源: 通知所有 Source 算子,从 Checkpoint 中记录的 Offset 开始重新消费数据。

通过这一机制,从上一个 Checkpoint 完成到故障发生之间所处理的所有数据及其产生的所有状态变更,都被“回滚”了。系统仿佛进行了一次时光倒流,然后从那个保存点重新开始处理,从而保证了内部状态的精确一次。


三、 端到端的精确一次

上述的 Checkpoint 机制完美保证了 Flink 内部状态的精确一次。然而,一个完整的流处理应用通常包含:

  • 输入源(Source): 如 Kafka, Pulsar
  • 处理逻辑(Flink Job)
  • 输出汇(Sink): 如 MySQL, Elasticsearch, Kafka, HBase

要保证端到端(End-to-End) 的精确一次,就必须确保数据从被源读取,到处理,再到最终写入输出汇的整个过程中,即使发生故障,结果也是精确一次的。

这需要外部系统也参与到 Flink 的分布式快照事务中来。Flink 通过 两阶段提交协议(Two-Phase Commit Protocol, 2PC) 来实现这一点。

两阶段提交 Sink 的工作原理

Flink 提供了通用的 TwoPhaseCommitSinkFunction 抽象类,用于实现支持 2PC 的 Sink。其工作流程与 Checkpoint 周期紧密绑定:

  1. 预提交阶段(Pre-commit)

    • 当 Checkpoint Barrier 流过 Sink 算子时,Sink 会触发 preCommit 操作。
    • 此时,Sink 会将当前批次的数据预先写入外部系统,但不提交(例如,写入 Kafka 的一个事务中,或者向数据库写入一条待提交的数据)。这个操作对外是不可见的。
    • Sink 将“预提交是否成功”的信息作为自己的状态,保存到当前的 Checkpoint 中。这意味着对外部系统的“预提交”动作被原子性地包含在了 Flink 的 Checkpoint 里。
  2. 提交阶段(Commit)

    • 当 JobManager 收到所有算子的 Ack,确认本次 Checkpoint 全局成功后,它会回调 Sink 算子的 commit 方法。
    • Sink 算子此时才正式提交之前预写入的事务(例如,提交 Kafka 事务),让数据真正对外可见。
  3. 中止阶段(Abort)

    • 如果 Checkpoint 失败(比如某个算子没有成功快照),JobManager 会回调 Sink 算子的 abort 方法。
    • Sink 算子则中止之前预提交的事务(例如,回滚 Kafka 事务),清理掉预写入的数据。

通过这种方式,Flink 确保了 Sink 端的数据输出与自身的 Checkpoint 成功与否保持原子性:要么整个 Checkpoint 成功,数据对外可见;要么整个 Checkpoint 失败,数据被完全撤销。


四、 幂等性

两阶段提交协议虽然强大,但也有一些缺点:

  • 协议开销: 预提交、提交、中止等操作需要与外部系统进行多轮交互。
  • 外部系统支持: 要求外部系统必须提供事务支持(如 Kafka 0.11+),这并非所有系统都具备。

在这种情况下,幂等性(Idempotence) 提供了一个更轻量级、更简单的替代方案。

什么是幂等性?

幂等性是指:一个操作被执行一次与被执行多次,对系统产生的副作用(Side Effect)是相同的。

一个经典的例子是:将某个账户的余额设置为 100 元。无论你执行这个操作一次、两次还是一百次,最终的结果都是余额为 100 元。这是一个幂等操作。而将余额增加 100 元则不是幂等的。

如何利用幂等性实现精确一次?

如果我们的 Sink 操作是幂等的,那么 Flink 的“至少一次”语义就可以轻松达到“端到端的精确一次”效果。

  • 工作流程

    1. Flink 内部仍使用 Checkpoint 机制保证状态是精确一次的。
    2. 在 Sink 端,我们设计一个幂等写入器
    3. 当发生故障并从 Checkpoint 恢复时,某些数据可能会被重复处理重复写入 Sink(即“至少一次”)。
    4. 但由于写入操作是幂等的,即使同一批数据被写了多次,结果也和只写一次完全相同。从外部看,效果就是精确一次的。
  • 实现关键

    • 为每一条数据生成一个唯一标识符(如 UUID,或由 源Topic+分区+Offset 组成)。
    • 在写入外部系统时,以这个唯一ID作为主键或唯一索引。
    • 当写入时,如果发现相同ID的数据已存在,则执行覆盖(UPDATE)或忽略(INSERT ... ON DUPLICATE KEY UPDATE)操作,而不是追加。

适用场景: 数据库(如 MySQL, HBase, Redis)的 UPSERT 操作,或者任何支持基于主键的覆盖写入的系统。


五、 总结与对比

机制原理优点缺点适用场景
Flink 内部 Checkpoint分布式快照 + 状态回滚原生支持,高效可靠只保障内部状态Flink 应用内部
两阶段提交 (2PC)与 Checkpoint 绑定的预提交和提交真正的端到端精确一次,通用性强延迟较高,需要外部系统支持事务Kafka、支持事务的数据库
幂等写入利用操作的幂等性对抗日志重复实现简单,延迟低,不要求事务需要设计唯一ID,只能用于支持幂等写入的系统支持 UPSERT 的数据库(MySQL, HBase, Redis)

结论

Flink 通过其精巧的分布式快照机制,为内部状态提供了坚固的精确一次保障。当需要与外部世界交互时,我们可以根据外部系统的能力,灵活选择两阶段提交幂等性方案来实现端到端的精确一次。

  • 如果外部系统支持事务,两阶段提交是最标准、最通用的选择。
  • 如果外部系统支持幂等写入(如多数数据库),那么采用幂等性方案通常更简单、更高效。

理解这两种模式的原理和适用场景,是设计一个高可靠性、高一致性 Flink 流处理应用的关键。Flink 的强大之处在于,它为我们提供了这两种强大的工具,以应对各种复杂的生产环境挑战。

=========================================================

人生得意须尽欢,莫使金樽空对月!
__一个热爱说唱的程序员。
今日份推荐音乐:杨宗纬/姚晓棠《我会好好的 (Live版)》

=========================================================

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/94925.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/94925.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Spring Boot 定时任务入门

1. 概述 在产品的色彩斑斓的黑的需求中,有存在一类需求,是需要去定时执行的,此时就需要使用到定时任务。例如说,每分钟扫描超时支付的订单,每小时清理一次日志文件,每天统计前一天的数据并生成报表&#x…

学习:uniapp全栈微信小程序vue3后台(6)

26.实现描述评分标签的双向数据绑定 /pages/wallpaper/picadd Array.prototype.splice() splice() 方法就地移除或者替换已存在的元素和/或添加新的元素。 二次确认 展现 确认标签 删除标签 温故知新: 标签: 关闭标签 27.uni-data-select调用云端分类…

Azure Marketplace 和 Microsoft AppSource的区别

微软的商业应用生态中,Azure Marketplace 和 Microsoft AppSource 是微软并行的两个主要“应用市场”(Marketplace),它们共同构成了微软的“商业市场”(Commercial Marketplace)计划,但服务的目…

完整实验命令解析:从集群搭建到负载均衡配置(2)

一、环境准备与基础网络配置1.1 节点角色与网络规划节点角色主机名所属网段IP 地址网关核心功能Web 服务器web110.1.8.0/2410.1.8.1110.1.8.10(后期调整为 10.1.8.20)部署 Nginx/HTTPD,提供 Web 服务Web 服务器web210.1.8.0/2410.1.8.1210.1.…

uniapp H5禁止微信浏览器长按出菜单,只针对图片

一、问题描述 如图:uni-image>img,img {pointer-events: none;-webkit-pointer-events: none;-ms-pointer-events: none;-moz-pointer-events: none; }uni-image::before {content: ;position: absolute;top: 0;bottom: 0;left: 0;right: 0;background: transpa…

【机器学习】 15 Gaussian processes

本章目录 15 Gaussian processes 515 15.1 Introduction 515 15.2 GPs for regression 516 15.2.1 Predictions using noise-free observations 517 15.2.2 Predictions using noisy observations 518 15.2.3 Effect of the kernel parameters 519 15.2.4 Estimating the kern…

Vue加载速度优化,verder.js和element.js加载速度慢解决方法

1. 使用CDN 这里把常用的vue、vuex、elementui、echarts、axios都引入成cdn的方式 1、在index.html引入CDN 找到public/index.html在上方引入下边的cdn。 [!NOTE] 引入script的时候,一定要把vue.js放到最上边,最先引入,不然后边的js加载会…

49.【.NET8 实战--孢子记账--从单体到微服务--转向微服务】--扩展功能--集成网关--Refit跨服务调用

Refit是一个用于.NET平台的REST库,它可以将REST API转换为实时类型安全的接口。通过Refit,我们可以轻松实现微服务之间的跨服务调用,使服务间通信变得更加简单和类型安全。本文将介绍如何在我们的项目中使用Refit来实现微服务间的通信。 一、什么是Refit Refit是一个强大的REST…

日志ELK、ELFK、EFK

一.ELK架构Elasticsearch Logstash Kibana 数据库日志处理日志显示1.logstash的使用(1)input:输入(2)filter:处理(3)output:输出2.ELFK架构Filebeat-->Elasticsearc…

【CUDA进阶】MMA分析Bank Conflict与Swizzle(下)

目录前言1. bank conflict 分析2. 通过 padding 解决 bank conflict3. mma 搭配 wmma 实现矩阵乘法计算3.1 代码实现3.2 补充:stmatrix_sync 函数分析3.3 补充:__shfl_sync 函数详解4. swizzle 原理讲解5. swizzle 实现思路讲解结语下载链接参考前言 学习…

天气查询系统

项目要求 项目知识点 问题与解决 代码分部 结果展示 项目要求 1.显示天气预报系统界面 2.系统可以通过选择城市配置获取不同城市天气信息 3.查看实时的天气信息 (当前温度、最高温度、最低温度、当前湿度、最高湿度、最低湿度、风向、风力、风级等信息&#x…

三重积分的对称性

文章目录前言柱面球面前言 规律作息 柱面 太牛了。我完全看不懂。实际上就类似于极坐标系。 球面 看到这么多东西,我真害怕。今天是 8.30 ,不管 9.10 有没有复习完概率的强化,我都一定要开始套卷,还有专业课的复习。ϕ\phiϕ…

深入理解 RabbitMQ:从底层原理到实战落地的全维度指南

引言: 本文总字数:约 18500 字预计阅读时间:45 分钟 为什么我们需要 RabbitMQ? 在当今分布式系统架构中,消息队列已成为不可或缺的核心组件。想象一下,当你在电商平台下单时,系统需要处理库存…

宽带有丢包,重传高的情况怎么优化

宽带丢包和重传率高是一个非常影响网络体验的常见问题。它会导致游戏卡顿、视频通话模糊、网页加载慢等。别担心,我们可以按照从易到难的顺序,系统地排查和优化。请遵循以下步骤:第一步:基础排查(自己动手,…

Kotlin 协程之Channel 的高阶应用

前言 了解了 Channel 的基础概念和基本使用 后,我们再来看一看 Channel 的特性以及高阶应用。 Channel 是"热流" 热流概念 Channel 是热流(Hot Stream),具备以下特性: 数据的生产和消费是两套独立的流程 …

PostgreSQL表空间(Tablespace)作用(管理数据库对象的存储位置)(pg_default、pg_global)

文章目录**1. 灵活的数据存储管理**- **逻辑与物理分离**:表空间为数据库对象(如表、索引)提供了一个逻辑名称与物理存储路径的映射。用户无需直接操作底层文件路径,只需通过表空间名称管理数据。- **多数据库共享表空间**&#x…

Ansible 核心运维场景落地:YUM 仓库、SSH 公钥、固定 IP 配置技巧

1:如何一次性验证所有主机能否被 Ansible 访问? 答:使用临时命令:ansible all -m ansible.builtin.ping或验证 sudo 是否正常:ansible all -m ansible.builtin.ping --become -K2:如何用 Ansible 统一配置…

rman导致的报错ORA-27037: unable to obtain file status

有套3节点的11204集群环境,在db2上配置了rman备份,今天例行检查时发现db1和db3上不定期有报错,报错如下:Control file backup creation failed:failure to open backup target file /u01/app/oracle/product/11.2.0/db_1/dbs/snap…

Kubernetes 与 GitOps 的深度融合实践指南

前言:在云原生技术飞速发展的今天,Kubernetes(简称 K8s)已成为容器编排领域的事实标准,而 GitOps 作为一种基于 Git 的云原生运维理念,正与 K8s 深度融合,为企业实现自动化、可追溯、可审计的应…

REST-assured 接口测试编写指南

REST-assured 简介 REST-assured 是一个基于 Java 的 DSL(领域特定语言)库,专门用于简化 RESTful API 测试的编写。它提供了流畅的 API 接口,使得测试代码更加易读易写,支持 JSON 和 XML 等多种响应格式的验证。 基本环…