状态(State)与一致性模型

接下来我们转向另一个在流处理中十分重要的点:状态(state)。状态在数据处理中是无处不在的。为了产生一个结果,函数一般会聚合某个时间段内(或是一定数量的)events的状态信息(例如计算聚合值,或是发现一个模式),有状态的 operators使用流的输入事件以及内部状态,计算出它们的输出。例如,一个滚动聚合operator输出当前它读入的所有的events的总和。Operator 持有当前sum的值作为它的内部状态,并在每次读入新值时对它做更新。类似,考虑一个operator在检测到“高温”后,若是在接下来的10分钟内检测到“烟”,则发出警报。此时operator需要将“高温”事件存储在它的状态信息中,直到看见“烟”事件,或是到达10分钟的过期时间。

由于流处理器可能会处理无限的数据,所以需要注意的是,不要让内部state无限地增长下去。为了限制state 大小,一般来说,operators会维护一些到目前为止看到的所有events的概要(synopsis)、或是总结(summary)信息。这个摘要信息可以是 计数、sum、 一个样本、亦或是用户自定义的一个数据结构(用于存储某些需要的属性)。

对于支持有状态的operators,会有以下挑战:

1. 状态管理

系统需要高效地管理state,并确保它可以被(合理地)并行更新

2. 状态分区

在并行处理时,场景较为复杂,因为输出的结果依赖于state以及持续输入的events。不过在大部分场景中,我们可以通过key将state分区,并单独的管理每个state。例如处理的输入流为一组传感器的events,这时可以使用分区的operator state 独立地维护每个传感器的状态信息。

3. 状态恢复

最大的挑战为:在发生错误时,有状态的operator需要确保state可以被恢复,并且仍能输出正确的结果。

接下来我们详细地讨论一下任务失败以及result guarantees。

任务失败

在流处理工作中,opratror state是非常重要的信息,需要对此有容错能力。如果在一次failure中,state丢失,则即使最终作业恢复了,输出的结果可能仍是不对的。流处理工作一般会持续运行较长时间,所以state可能会在几天(甚至几月)才会被收集一次。如果重新去处理所有的输入,以生成丢失的state,会是一个费时费算力的过程。

在实际场景中,可以经常见到有上百个并行任务(task)的流作业。而在长期运行的流作业中,每个任务在任何时间都有可能失败。如何确保这些故障可以被透明地处理,并让流工作继续运行?事实上,我们需要流处理器不仅可以在任务失败时仍能继续处理,还需要保证结果以及operator state的正确性。接下来我们会对此讨论具体细节。

什么是一个任务失败

对于输入流里的每一个event来说,一个任务是一个处理步骤,包含以下几步:(1)接收到event,将它存储在本地缓存;(2)可能会更新内部state;并(3)生成一个输出条目。而故障可能在以上任意一步发生。如果故障发生在第一步,event是否会丢失?如果在已经更新了state后发生故障,state的信息在任务恢复后是否再次被更新?而在这些场景下,最终输出的结果是否仍是准确的?

流系统通过提供结果保障(result guarantees)定义任务在故障发生时的行为。下面我们会介绍主流流处理器提供的保障(guarantees),以及为了达到这些guarantees,系统实现的一些机制。

至多一次(AT-MOST-ONCE

当一个任务失败时,最简单的做法是不做任何事。至多一次确保每个event仅被处理一次 。也就是说,失败了就失败了。events可以简单的被丢弃,并且不做任何事去确保结果的正确性。这种guarantee也被称为“没有保障“(no guarantee),因为一个丢弃所有events的系统也可以提供这种保障。没有保障这点可能听起来是一个比较差的想法,但是如果你关注的是尽量少的延迟,并且系统并不要求很高的准确性,则这也是一个可接受的选择。

至少一次(AT-LEAST-ONCE

在大部分真实应用中,我们会希望events不应该丢失。这种guarantee被称为至少一次,意思是:所有的events均会被处理,并且有些可能会被处理不止一次。如果应用的准确性仅取决于所有事件的完整性,则重复的处理可能也是能被接受的。例如,如果场景是判断某个特定的event是否在流中出现,则可以使用此guarantee。但是如果是判断此特定event在流中出现的次数,则使用此gurantee会返回错误的结果。

为了确保at-least-once结果的准确性,我们需要有一种方式replay events(从数据源或是缓冲区)。持久化的 event log会将events写入到可靠存储,所以在task失败时,这些events可以被replay。另一种达到同样效果的方法是使用 记录确认(record acknowledgments)。此方法会在缓存中存储每个event,直到某个event被管道中所有的task 确认处理后,此event才会被丢弃。

精确一次(EXACTLY-ONCE

精确一次是最严格的guarantee,并且很难达成。精确一次意思是:不仅没有event丢失,而且在更新state时,每个event仅被应用一次。本质上说,exactly-once guarantee 表示应用会提供准确的结果,就像故障没有发生一样。

提供exactly-once guarantee需要at-least-once guarantees,所以数据replay的机制也是必须的。此外,流处理器还需要确保internal state的一致性。也就是说,在从错误恢复后,它应该能够知道,一个event是否已经被state使用了。事务更新(transactional updates)是一种实现它的方式,但是它会引发大量性能开销的问题。在Flink中,它用了一个轻量级的快照机制(snapshotting)达成exactly-once result guarantee。会在之后的章节进一步讨论。

端到端精确一次END-TO-END EXACTLY-ONCE

到目前为止我们所见到的各种guarantees,都表示的是:由流处理器(stream processor)管理的application state。在真实的流应用中,除了流处理器外,都至少会有一个source和一个sink。End-to-end guarantees表示的是在整个数据处理pipeline中的结果准确性。每个组件提供了它自己的guarantee,所以整个pipeline的 end-to-end guarantee 是每个组件中最弱的那个guarantee。需要注意的是,有时候使用较弱的guarantees可能也能获取更强guarantee的语义。一个常见的案例是:当一个task求最大值或最小值的时,使用at-least-once guarantess即可达到exactly-once语义的效果。

总结

到现在为止,我们独立于Flink介绍了流处理中的一些概念,在之后的章节中,我们会介绍Flink是如何实现的这些概念,以及如何使用DataStream API 去编写应用程序并使用介绍到的这些功能。

References

Vasiliki Kalavri, Fabian Hueske. Stream Processing With Apache Flink. 2019

Flink流处理(五)- 状态与一致性模型的更多相关文章

  1. Flink架构(五)- 检查点,保存点,与状态恢复

    检查点,保存点,与状态恢复 Flink是一个分布式数据处理系统,这种场景下,它需要处理各种异常,例如进程终止.机器故障.网络中断等.因为tasks在本地维护它们的state,Flink必须确保在出现故 ...

  2. Flink流处理(一)- 状态流处理简介

    1. Flink 简介 Flink 是一个分布式流处理器,提供直观且易于使用的API,以供实现有状态的流处理应用.它能够以fault-tolerant的方式高效地运行在大规模系统中. 流处理技术在当今 ...

  3. flink流处理从0到1

    一.DataStream API之Data Sources(消费者之数据源) 介绍: source是程序的数据源输入,你可以通过StreamExecutionEnvironment.addSource ...

  4. 带你玩转Flink流批一体分布式实时处理引擎

    摘要:Apache Flink是为分布式.高性能的流处理应用程序打造的开源流处理框架. 本文分享自华为云社区<[云驻共创]手把手教你玩转Flink流批一体分布式实时处理引擎>,作者: 萌兔 ...

  5. 转:Windows Socket五种I/O模型

    原文转自:  Windows Socket五种I/O模型 Winsock 的I/O操作: 1. 两种I/O模式 阻塞模式:执行I/O操作完成前会一直进行等待,不会将控制权交给程序.套接字 默认为阻塞模 ...

  6. I/O模型之一:Unix的五种I/O模型

    目录: <I/O模型之一:Unix的五种I/O模型> <I/O模型之二:Linux IO模式及 select.poll.epoll详解> <I/O模型之三:两种高性能 I ...

  7. Windows Socket五种I/O模型——代码全攻略(转)

    Winsock 的I/O操作: 1. 两种I/O模式 阻塞模式:执行I/O操作完成前会一直进行等待,不会将控制权交给程序.套接字 默认为阻塞模式.可以通过多线程技术进行处理. 非阻塞模式:执行I/O操 ...

  8. State Processor API:如何读取,写入和修改 Flink 应用程序的状态

    过去无论您是在生产中使用,还是调研Apache Flink,估计您总是会问这样一个问题:我该如何访问和更新Flink保存点(savepoint)中保存的state?不用再询问了,Apache Flin ...

  9. CAP原理、一致性模型、BASE理论和ACID特性

    CAP原理 在理论计算机科学中,CAP定理(CAP theorem),又被称作布鲁尔定理(Brewer's theorem),它指出对于一个分布式计算系统来说,不可能同时满足以下三点: 一致性(Con ...

随机推荐

  1. 题解 P5712 【【深基3.例4】Apples】

    题目传送门 思路 仔细读题后,我们可以发现,输出可以分成\(2\)种情况,apple加s与apple不加s,所以我们可以使用if/else来实现. 接着,我们读入n. int n; cin>&g ...

  2. 生产环境容器落地最佳实践 --JFrog 内部K8s落地旅程

    引言 Kubernetes已经成为市场上事实上领先的编配工具,不仅对技术公司如此,对所有公司都是如此,因为它允许您快速且可预测地部署应用程序.动态地伸缩应用程序.无缝地推出新特性,同时有效地利用硬件资 ...

  3. Docker最全教程——从理论到实战(十五)

    前言 Java是一门面向对象的优秀编程语言,市场占有率极高,但是在容器化实践过程中,发现官方支持并不友好,同时与其他编程语言的基础镜像相比(具体见各语言镜像比较),确实是非常臃肿. 本篇仅作探索,希望 ...

  4. 二叉堆(2)LeftistHeap

    左倾堆,用于堆的快速合并. 规则: ① 节点的键值小于或等于它的左右子节点的键值. ② 节点的左孩子的NPL >= 右孩子的NPL. ③ 节点的NPL = 它的右孩子的NPL + 1. 测试文件 ...

  5. java - synchronized与lock的区别

    synchronized与lock的区别 原始构成 synchronized是关键字属于JVM层面 monitorenter(底层是通过monitor对象来完成,其实wait/notify等对象也依赖 ...

  6. 下载 Microsoft JDBC driver 7.2 for SQL Server

    下载 Microsoft JDBC driver 7.2 for SQL Server:https://www.microsoft.com/zh-cn/download/confirmation.as ...

  7. 关于spring整合前两大框架的一些小问题04

    关于spring中对延迟关闭session的配置,以及工具类BaseDao和BaseAction 一.HibernateTemplate执行查询时的一些小问题 1.当两个PO类的关系是多对一时: 我们 ...

  8. [SDOI2013] 直径 - 树形dp

    对于给定的一棵树,其直径的长度是多少,以及有多少条边满足所有的直径都经过该边. Solution 有点意思 先随便求一条直径(两次DFS即可),不妨设为 \(s,t\),我们知道要求的这些边一定都在这 ...

  9. WSO2 ESB XML定义语法(1)

    1.(基于Apache Synapse的WSO2 ESB实现)参考文件位置: http://synapse.apache.org/userguide/config.html 基于Apache Syna ...

  10. PHP对一维数组去重

    一维数组去重 $arr =[1,2,2,3,6]; $arr1 =array_flip($arr); $arr =array_flip($arr1); return $arr; array_flip( ...