Exactly Once语义在Flink中的实现 | 青训营笔记

80 阅读4分钟

这是我参与「第四届青训营 」笔记创作活动的第三天

数据流和动态表

  • 传统SQL和流处理
特征SQL流处理
处理数据的有界性处理的表是有界的流是一个无限元组序列
处理数据的完整性执行查询可以访问完整的数据执行查询无法访问所有数据
执行时间批处理查询,产生固定大小结果后终止查询不断更新结果,永不停止
  • 数据流和动态表的转换

数据流->动态表->连续查询->动态表->数据流

动态表:随时间变化的表,因为数据是源源不断的输入的,所以表也一直在增长

  • 连续查询
  1. 查询从不终止
  2. 查询结果不断更新,产生一个新的动态表
  • 三种连续查询实例

    • 连续查询网站的点击量

      查询结果不断增加,更新先前输出的结果

      即定义结果表的changelog流包括INSERTUPDATA

    • 查询产生仅追加数据的动态表

      (以1小时为分割点,查询每小时的点击量)

      查询只附加到结果表,即结果表的changelog只包含INSERT操作

    • Retract消息的产生

    还是查点击量。注意当Mary第2次点击时,先执行了Mary-1的操作,即retract回撤操作,然后再执行Mary+2

  • 状态

需要存储的每个用户的URL计数,以便能够增加该计数并在输入表接收新行时发送新结果

  • 不同数据处理保证的语义

    • At-most-once:出现故障的时候啥也不做,数据处理不保证任何语义,处理时延低
    • At-least-once:保证每条数据均至少被处理一次,一条数据可能存在重复消费
    • Exactly-once:最严格的处理语义,从输出结果来看,每条数据均被消费且仅被消费一次,仿佛故障没有发生

Exactly-Once 和 Checkpoint

  • 制作快照的时间点

    • 状态恢复的时间点:需要等待所有处理逻辑消费完成,source保留状态及之前的数据

    对状态恢复的时间点有要求的原因:例:source读到5了,偶数累加器加到6,奇数累加器如果还没有把5加进去,和还是4.如果从这里保存 节点,等到恢复的时候,奇数累加器还是4,并不是我们想要的9。

    • 一个简单的快照制作算法

      1. 暂停处理输入的数据
      2. 等待所以算子消费完当前输入的数据
      3. 第二步结束后,所有算子复制自己当前状态,并保存到远端可靠存储
      4. 恢复对输入数据的处理
  • Chandy-Lamport算法

  • checkpoint对作业性能的影响

    • 每个算子完成状态快照之后就可以正常处理数据了,不用等下游算子制作完成快照
    • 在快照制作和Barrier Alignment过程仍需暂停处理数据,仍会增加延迟
    • 快照保存到远端,可能会耗时

端到端Exactly-Once实现

  • Checkpoint能保证每条数据都对各个有状态的算子更新一次,但sink输出算子仍可能下发重复的数据

严格意义的端到端的Exactly-Once需要特殊的sink算子实现

  • 两阶段提交协议

概念:在多个节点参与执行的分布式系统中,为了协调每个节点都能同时执行或回滚某个事务性操作,(要么全做完要么全不做),引入了一个中心节点来统一处理所有节点的执行逻辑。这个中心节点叫做协作者(Coordinator),被中心节点调度的其他业务节点叫做参与者(Participant)

阶段

  • 预提交阶段:

1.协作者向所有参与者发送一条commit消息

2.所有协作者收到消息之后,执行事物,但不真正提交

3.若事物成功执行完成,发送一个成功的消息(vote yes),反之,发送失败消息(vote no)

提交阶段分为两种情况

  • 若协作者成功接收到所有参与者vote yes的消息
  1. 协作者向所有参与者发送一个commit消息
  2. 每个收到commit消息的参与者释放执行事物所需的资源,并结束事务的执行
  3. 完成步骤2后,参与者发送一个ack消息给协作者
  4. 协作者收到参与者的所有ack消息后,标识事务完成
  • 若协作者收到参与者vote no消息
  1. 协作者向所有参与者发送rollback消息
  2. 每个收到rollback消息的参与者回滚事务的执行操作,并释放事务所占资源
  3. 完成2后,参与者发送一个ack给协作者
  4. 协作者收到所有参与者的ack后,标识该事务成功完成回滚
  • Flink中的两阶段提交协议

  • 小结

Flink案例讲解

账单计算服务

  • 场景简介:从Kafka读取账单信息,进行处理后写入MySQL中