Flink中的状态一致性

这篇具有很好参考价值的文章主要介绍了Flink中的状态一致性。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1.概念

  一致性其实就是结果的正确性。对于分布式系统而言,从不同节点读取时总能得到相同的值;而对于事务而言,是要求提交更新操作后,能够读取到新的数据。

  • 有状态的流处理,内部每个算子任务都可以有自己的状态。
  • 对于流处理内部来说,所谓状态一致性,其实就是所说的计算结果要保证准确。
  • 一条数据不应该丢失,也不应该重复计算。
  • 在遇到故障时可以状态恢复,恢复以后重新计算,计算结果也是完全正确的。

2.一致性级别

  • AT-MOST-ONCE(最多一次)
  • 当任务发生故障时,直接重启,别的什么都不干;既不恢复丢失的状态,也不重放丢失的数据。每条数据在正常情况下会被处理一次,遇到故障时就会丢掉。即为每条消息就只消费一次。
  • AT-LEAST-ONCE(至少一次)
    • 所有的数据都不会丢,肯定被处理了;不过不能保证只处理一次,有些数据会被重复处理。在某些场景下,重复处理数据是不会影响结果的正确性。比如:统计某电商网站的UV。
  • EXACTLY-ONCE(精确一次
    • 所有数据不仅不会丢失,而且只会被处理一次,不会重复处理。Flink中使用的是一种轻量级快照机制—检查点(checkpoint)来保证exactly-once语义。

3.端到端精确一次(end-to-end exactly-once)

  对于Flink内部来说,检查点机制可以保证故障恢复之后数据不丢(在能够重复放的情况下),并且只处理一次,所以已经可以做到exactly-once的一致性语义了。故端到端一致性的关键点,就在于输入的数据源端和输出的外部存储端。

3.1 输入端保证

  输入端主要指的就是Flink读取的外部数据源。想要在故障恢复后不丢数据,外部数据源就必须拥有重放数据的能力。常见做法就是对数据进行持久化保存,并且可以重设数据的读取位置。一个最经典的应用就是Kafka。在Flink的Source任务中将数据读取的偏移量保存为状态,这样就可以在故障恢复时从检查点中读取出来,对数据源重置偏移量,重新获取数据。

3.2 输出端保证

  输出端主要指的就是Flink处理完数据,通过sink任务输出到外部系统。对于输出端,需要保证在故障恢复时,数据不会重复写入外部系统。对于输出端,有两种 具体的实现方式:幂(Idempotent)写入和事务性(Transactional)写入。

3.2.1 幂等(idempotent)写入

  所谓“幂等”操作,就是说一个操作可以重复执行很多次,但只导致一次结果更改。这种方式主要限制在于外部存储系统必须支持这样的幂等写入。

  对于幂等写入,在遇到故障恢复时,可能会出现短暂的不一致。因为保存点完成之后到发生故障之间的数据,其实已经写入了一遍,回滚的时候并不能消除它们。不过当数据的重放逐渐超过发生故障的点的时候,最终的结果还是一致的。

3.2.2 事务(transaction)写入

  输出端最大的问题,就是写入到外部系统的数据难以撤回。而利用事务就可以实现对已写入数据的撤回。在Flink流处理的结果写入外部系统时,如果能够构建一个事务,让写入操作可以随着检查点来提交和回滚,这样就解决了重复写入的问题。 事务与检查点是绑定在一起的,当Sink任务遇到barrier时,开始保存状态的同时就开启一个事务,后续所有数据的写入都在该事务中;待到当前检查点保存完毕时,将事务提交,所有写入的数据就真正可用了。如果中间过程出现故障,状态会回退到上一个检查点,而当前事务没有正常关闭(因为当前检查点没有保存完),所以也会回滚,写入到外部的数据就被撤销了。对于事务写入有两种实现方式:预写日志(WAL)和两阶段提交(2PC)。

预写日志(write-ahead-log,WAL)

实现步骤:

  1. 先把结果数据作为日志(log)状态保存起来;
  2. 进行检查点保存时,同时将这些结果数据做持久化存储;
  3. 在收到检查点完成的通知时,将所有结果一次性写入外部系统。

  预写日志这种批写入的方式,有可能会写入失败;所以在写入动作之后,必须等待发送成功的返回确认消息。在成功写入所有数据后,内部再次确认相应的检查点,此时代表着检查点的真正完成。同时也需要确认信息也进行持久化保存,在故障恢复时,只有存在对应的确认信息,才能保证这批数据已经写入,可以恢复到对应的检查点位置。

两阶段提交(two-phase-commit,2PC)

  两阶段提交,顾名思义,先做“预提交”,等检查点完成之后再正式提交。这种提交方式是真正基于事务的,它需要外部系统提供事务支持。

实现步骤:

  1. 当第一条数据到来时,或者收到检查点的分界线时,Sink任务都会启动一个事务。
  2. 接下来接收到的所有数据,都通过这个事务写入外部系统;这时由于事务没有提交,数据虽然写入了外部系统,但是不可用,是“预提交”的状态。
  3. 当Sink任务收到JobManager发来检查点完成的通知时,正式提交事务,写入的结果就真正可用了。

  当中间发生故障时,当前未提交的事务就会回滚,于是所有写入外部系统的数据也就实现了撤回。两阶段提交的方式充分利用了Flink现有的检查点机制:分界线的到来,就标志着开始一个新事务;而收到来自JobManager的checkpoint成功的消息,就是提交事务的指令。

两阶段提交对外部系统有要求:

  • 外部系统必须提供事务支持,或者Sink任务必须能够模拟外部系统上的事务。
  • 在检查点的间隔期间里,必须能够开启一个事务并接受数据写入。
  • 在收到checkpoint完成的通知之前,事务必须是“等待提交”的状态。在故障恢复的情况下,这可能需要-些时间。如果这个时候sink系统关闭事务(例如超时了) ,那么未提交的数据就会丢失
  • sink任务必须能够在进程失败后恢复事务 。
  • 提交事务必须是幂等操作。

3.3 总结

对于端到端的精准一次而言:

系统 要求
source端 可重设数据的读取位置
Flink内部 依赖checkpoint
sink端 从故障恢复时,数据不会重复写入外部系统

4.Flink和Kafka连接时的精确一次保证

4.1 概述

  Flink与Kafka连接时属于端到端精准一次,可以从三个组件的角度进行分析:

  • Flink内部
    • 通过checkpoint机制, 把状态存盘,发生故障的时候可以恢复,保证内部的状态一致性。
  • 输入端
    • 输入数据源端的Kafka可以对数据进行持久化保存,并可以重置偏移量(offset)。在Source任务(FlinkKafkaConsumer)中将当前读取的偏移量保存为算子状态,写入到检查点中;当发生故障时,从检查点中读取恢复状态,并由连接器FlinkKafkaConsumer向Kafka重新提交偏移量,就可以重新消费数据、保证结果的一致性了。
  • 输出端
    • 输出端保证exactly-once的最佳实现,当然就是两阶段提交(2PC)。Flink官方实现的Kafka连接器中,提供了写入到Kafka的FlinkKafkaProducer,它就实现TwoPhaseCommitSinkFunction接口。
    • 两阶段提交:处理完毕得到结果,写入Kafka时是基于事务的“预提交”;等到检查点保存完毕,才会提交事务进行“正式提交”。

4.2 2PC具体步骤

情景: 由Flink从Kafka读取数据、并将处理结果写入Kafka,如图所示

Flink中的状态一致性,flink,flink,数据库,sql

  Flink与Kafka连接的两阶段提交,离不开检查点的配合,这个过程需要JobManager协调各个TaskManager进行状态快照,而检查点具体存储位置则是由状态后端(State Backend)来配置管理的。一般情况,我们会将检查点存储到分布式文件系统上。

(1) 启动检查点保存

  检查点保存的启动,标志着进入了两阶段提交协议的“预提交”阶段。当然,现在还没有具体提交的数据。

Flink中的状态一致性,flink,flink,数据库,sql

  JobManager通知各个TaskManager启动检查点保存,Source任务会将检查点分界线(barrier)注入数据流。这个barrier可以将数据流中的数据,分为进入当前检查点的集合和进入下一个检查点的集合。

(2) 算子任务对状态做快照

  分界线(barrier)会在算子间传递下去。每个算子收到barrier时,会将当前的状态做个快照,保存到状态后端。

Flink中的状态一致性,flink,flink,数据库,sql

  Source任务将barrier插入数据流后,也会将当前读取数据的偏移量作为状态写入检查点,存入状态后端;然后把barrier向下游传递,自己就可以继续读取数据了。接下来barrier传递到了内部的Window算子,它同样会对自己的状态进行快照保存,写入远程的持久化存储。

(3) Sink任务开启事务,进行预提交

Flink中的状态一致性,flink,flink,数据库,sql

  分界线(barrier)终于传到了Sink任务,这时Sink任务会开启一个事务。后续到来的所有数据,Sink任务都会通过该事务来写入Kafka。这里barrier是检查点的分界线,也是事务的分界线。由于之前的检查点可能尚未完成,因此上一个事务也可能尚未提交;此时barrier的到来开启了新的事务,上一个事务尽管可能没有被提交,但也不再接收新的数据了。

  对于Kafka而言,提交的数据会被标记为“未确认”(uncommitted)。这个过程就是所谓的“预提交”(pre-commit)。

(4) 检查点保存完成,提交事务

  当所有算子的快照都完成,也就是这次的检查点保存最终完成时,JobManager会向所有任务发确认通知,告诉TaskManager当前检查点已成功保存。

Flink中的状态一致性,flink,flink,数据库,sql

  当Sink任务收到确认通知后,就会正式提交之前的事务,把之前“未确认”的数据标为“已确认”,接下来就可以正常消费了。文章来源地址https://www.toymoban.com/news/detail-729510.html

4.3 需要的配置

  • 必须启用checkpoint。
  • 在FlinkKafkaProducer的构造函数中传入参数Semantic.EXACTLY_ONCE。
  • 配置Kafka(写入的外部系统)读取数据的消费者的隔离级别:isolation.level=read_commited。
  • 事务超时配置:Flink的Kafka连接器中配置的事务超时时间transaction.timeout.ms默认是1小时,而Kafka集群配置的事务最大超时时间transaction.max.timeout.ms默认是15分钟。实际配置应该是:transaction.timeout.ms≤transaction.max.timeout.ms。

到了这里,关于Flink中的状态一致性的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 基于 Flink & Paimon 实现 Streaming Warehouse 数据一致性管理

    摘要:本文整理自字节跳动基础架构工程师李明,在 Apache Paimon Meetup 的分享。本篇内容主要分为四个部分: 背景 方案设计 当前进展 未来规划 点击查看原文视频 演讲PPT ​ 早期的数仓生产体系主要以离线数仓为主,业务按照自己的业务需求将数仓分为不同的层次,例如 DW

    2024年02月14日
    浏览(44)
  • CHI中一致性状态简介

    Coherence Protocol 各个状态描述(只描述有意思的); I  Invalid: UC  Unique Clean: □ 当前cacheline可以直接修改,不用通知其他RN或HN; □ HNF来snoop时,数据可以返回给HNF, 也可以不返回; □ HNF来snoop时,数据可以直接返回给原始的RN; UCE  Unique Clean Empty: □ 当前cacheline可以直接修改,

    2024年02月15日
    浏览(45)
  • Redis 原理缓存过期、一致性hash、雪崩、穿透、并发、布隆、缓存更新策略、缓存数据库一致性

    redis的过期策略可以通过配置文件进行配置 redis会把设置了过期时间的key放在单独的字典中,定时遍历来删除到期的key。 1).每100ms从过期字典中 随机挑选20个,把其中过期的key删除; 2).如果过期的key占比超过1/4,重复步骤1 为了保证不会循环过度,导致卡顿,扫描时间上限

    2024年02月08日
    浏览(58)
  • 缓存和数据库一致性

    项目的难点是如何保证缓存和数据库的一致性。无论我们是先更新数据库,后更新缓存还是先更新数据库,然后删除缓存,在并发场景之下,仍然会存在数据不一致的情况(也存在删除失败的情况,删除失败可以使用异步重试解决)。有一种解决方法是延迟双删的策略,先删

    2024年01月17日
    浏览(45)
  • 缓存和数据库一致性问题分析

    目录 1、数据不一致的原因 1.1 并发操作 1.2 非原子操作 1.3 数据库主从同步延迟 2、数据不一致的解决方案 2.1 并发操作 2.2 非原子操作 2.3 主从同步延迟 2.4 最终方案 3、不同场景下的特殊考虑 3.1 读多写少的场景 3.2 读少写多的场景 导致缓存和数据库数据不一致的原因有三个

    2024年02月14日
    浏览(42)
  • 分布式数据库-事务一致性

    version: v-2023060601 author: 路__ 分布式数据库的“强一致性”应该包含两个方面: serializability(串行) and linearizability(线性一致) ,上述图为“Highly Available Transactions: Virtues and Limitations”论文中对于一致性模型的介绍。图中箭头表示一致性模型之间的关系。对于异步网络上的分

    2024年02月08日
    浏览(53)
  • 【大数据】流处理基础概念(三):状态和一致性模型(任务故障、结果保障)

    流处理基础概念(一):Dataflow 编程基础、并行流处理 流处理基础概念(二):时间语义(处理时间、事件时间、水位线) 流处理基础概念(三):状态和一致性模型(任务故障、结果保障) 😊 如果您觉得这篇文章有用 ✔️ 的话,请给博主一个一键三连 🚀🚀🚀 吧 (点

    2024年01月25日
    浏览(49)
  • 如何保证缓存和数据库的数据一致性

    若数据库更新成功,删除缓存操作失败,则此后读到的都是缓存中过期的数据,造成不一致问题。 同删除缓存策略一样,若数据库更新成功缓存更新失败则会造成数据不一致问题。 若缓存更新成功数据库更新失败, 则此后读到的都是未持久化的数据。因为缓存中的数据是易

    2023年04月19日
    浏览(58)
  • Redis和数据库保持数据一致性方案

    Redis和数据库一致性又称为“双写一致性”,在分布式系统中,由于多个节点之间的并发读写操作,可能导致数据不一致的情况发生。本文将着重介绍如何通过使用Redis与数据库相结合的方案来实现数据一致性。 首先,读取数据时都是先查询Redis,命中则直接返回,未命中则先

    2024年02月11日
    浏览(88)
  • Redis如何保证缓存和数据库一致性?

    现在我们在面向增删改查开发时,数据库数据量大时或者对响应要求较快,我们就需要用到Redis来拿取数据。 Redis:是一种高性能的内存数据库,它将数据以键值对的形式存储在内存中,具有读写速度快、支持多种数据类型、原子性操作、丰富的特性等优势。 优势: 性能极高

    2024年01月16日
    浏览(70)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包