本文整理自公司组内集体学习分享的讲稿,简单的介绍了流处理领域的一些基本概念,主要是抄袭Tyler Akidau 的两篇文章 Streaming 101/102。 两篇不长的文章,对流式处理和其解决的问题有很好的诠释。Tyler之后又受邀把这两篇文章扩成 Streaming System 一书,非常值得一看。可惜同事们都没怎么认真读T_T。
考虑到同事大多之前没有接触过流处理(系统),所以这篇文章主要侧重于流处理的概念入门。内容没有涉及具体的框架 API,不讨论流式框架实现的原理, 也不会对概念细节作深度讨论(其实我也不懂)。
什么是流处理
计算机领域中,流(Stream)是一个常见的概念,如TCP 流,视频流,Java Stream API等等。 他们之间的共性是,尽管由一个个独立的元素组成(TCP的Packet,视频的帧等等),对外的接口呈现的是一个连续不断出现的整体(艾玛,太抽象了)。
Tyler对流的定义是:
不断增长,趋于无穷的数据集。A type of ever-growing, essentially infinite data set.
以我司的场景举例,每日的学生上课人数就是一个流,这个流里包含了8月1日 的所有课程的上课的学生的人数,包含了8月2日的,3日的,向未来不断延伸。
流处理(Streaming Processing)就是考虑到流特性的处理模型。由于早期流式处理引擎的不完善,很多人对流处理有不准确的认知,总是将流处理与“低延时”,“估算”关联起来, 为了消歧义,Tyler重新定义了一套名词:
- 流即无限数据集(Unbounded Data Set)。
- 对应的,流处理即对无限数据集的处理(Unbounded Data Processing)。
同样的,批处理就成了对有限数据集的处理(Bounded Data Processing)。有限/无限称作数据集的基数(Cardinality)。
人们习惯把流处理和批处理看成两种完全不同的模型,重命名后,我们可以看出,批处理是流处理的一个子集。如果一个模型可以处理无限的数据集,为什么不可以处理有限的数据集呢? 这也解释了另外一个问题:为什么批处理会早成熟若干年。自然而然,处理有限数据集要比处理无限数据集简单。
流式系统的能力
人们对低延迟数据处理的需求是一直存在的,有些信息具有很高的时效性,例如,微博需要尽可能快的展现当前的热点消息, 如果等到一天之后批处理跑完数据,黄花菜都凉了。(Justice delayed is justice denied)
处理有限数据集式,数据是静态完整的。批系统有计算所需要的所有知识。而在处理无限数据集时,情况要复杂的太多。数据流是混乱的,数据的到达可能重复,乱序,丢失。 数据流是不断增长的,怎么能保证系统即便出现崩溃,又能重现相同的结果呢? 在这些问题解决之前,批处理依然要承担主要的数据处理责任。流式系统一段时间内只能作为批式系统的辅助,准确可靠的数据依然要依赖于批式系统。
Twitter提出了Lambda架构,希冀能够同时利用两种模型的好处。 Lambda架构中,同一数据流,会被流式系统和批式处理系统各处理一遍。流式系统提供低延时的估算结果,批式系统提供迟到的正义。不幸的是,这套系统没有取得预期的效果,原因如下:
- 一套逻辑维护在两个系统中,是很麻烦的一件事情。
- 用户宁愿去看延时的批处理数据,也不愿信任准时的流式系统数据。
Lambda架构的失败,说明了懒惰和缺乏信任是当代社会的两大顽疾。总而言之,修正主义是行不通滴。
搞定了正确性,流式系统就有了和批式系统平起平坐的资格,这是横亘在长征路上的最后一座大山。 Spark Streaming一声炮响,为业界送来了Exactly-once Processing(注意区别Exactly-once delivery),从此流式系统的语义挣脱了At-least once和at-most once,翻身作了主人。 批式系统能准确处理的数据集,流处系统也能准确处理了。
这还不够,流式系统要做无限数据集的处理,还需要一个批式系统不具备的能力:推理时间(Reason about Time)。这是流式系统超越批式系统的地方。
时间域
要推理时间,首先要对时间有所认知。流式系统中,每个数据都存在着若干时间域(Time Domain),如
- 事件时间(Event Time),即数据真实发生的时间。
- 处理时间(Processing Time),即系统观察到事件的时间。
理想情况下,事件时间和处理时间相等,事件发生时即可被观察到。现实中自然是不可能的:
- 数据的传递本身需要时间。
- 网络状况等外界因素的影响,事件时间到处理时间的延迟也不同。
在大多数场景下,结果的正确性需要使用事件时间。现实世界事件时间和处理时间之间不可控的延时,导致永远无法确保一定能得到完整的结果。这就需要系统有推理时间窗口完整性的能力, 需要系统即便数据迟到也能更新完善计算结果的能力。
数据处理模式
无限数据集的处理,往往离不开下面四个问题。
计算的结果是什么?(What results are calculated?)
流计算的结果由一个个转换(Transformation)组成。
可能的形式有:
- 元素级别(Element-wise),如 Map
- 聚合(Grouping),如 Sum
- 组合(Compositing),如 Map + Sum
元素级别的转换和聚合的区别是,聚合是有状态的,要比无状态的元素级别转换复杂很多。下面的三个问题,都可以看作是针对聚合转换的。
在什么时间范围里计算?(Where in event time are results calculated?)
计算可以发生在窗口(Window)之中,窗口在时间域上将数据分成若干份。
常见的窗口形式:
- 固定窗口
- 滑动窗口
- 会话窗口
何时输出计算结果?(When in processing time are results materialized?)
- 触发器(Triggers)
- 水位(Watermark)
何时输出计算结果?(When in processing time are results materialized?)
触发器(Triggers)控制结果输出。触发器可被下列信号触发:
- Event Time
- Processing Time
- 窗口内事件的数量
- 特殊的事件元素。
水位(Watermark)是衡量当前窗口是否完成的标志。简单来看,水位是 Processing Time 到 Event Time 的一个映射, F(P) -> E。 给定一个 Processing Time,即标志得到的 Event Time 之前的事件均已处理完毕。因此水位必须是单调增函数。
真实世界中,得到完美水位是几乎不可能的,通常会要采用启发式的方法。水位保证的是数据的完整性。
如何完善计算结果(How do refinements of results relate?)
有几种模式:
- 抛弃(discarding)
- 累积(accumulate)
- 撤回并累计(accumulate + retraction)
完善结果需要存储的支持。
数据处理框架
数据处理框架做了什么?
- 抽象的编程模型,提供语义保证。
- 提供 Scalability。
- Fault Tolerance。
现有的数据处理框架
Tyler在一次演讲中对现有的数据处理框架作了对比。
Apache Flink
Apache Flink is a framework and distributed processing engine for stateful computations over unbounded and bounded data streams
特点
- Exactly-once state consistency
- Event-time processing
- Checkpoint & Savepoint
- Queryable state store
- Metrics
- High Throughput & Low Latency
性能
- 30 Machines, 120 cores
throughput: 1.5 M events/sec, .99 latency 20ms
throughput: 80 M events/sec, .99 latency 50ms \\
更多的问题
- Window Join
- Watermark propagation
- Stream SQL
- GC
- Back Pressure
- Parallelism
(我一个都不懂 -_-)
更多阅读
- You Cannot Have Exactly-Once Delivery.[https://bravenewgeek.com/you-cannot-have-exactly-once-delivery/]
- You Cannot Have Exactly-Once Delivery Redux. [https://bravenewgeek.com/you-cannot-have-exactly-once-delivery-redux/]
- Why local state is a fundamental primitive in stream processing[https://www.oreilly.com/ideas/why-local-state-is-a-fundamental-primitive-in-stream-processing]
- Apache Flink: Stream and Batch Processing in a Single Engine.[http://asterios.katsifodimos.com/assets/publications/flink-deb.pdf]
- MillWheel: Fault-Tolerant Stream Processing at Internet Scale. [https://ai.google/research/pubs/pub41378]
- I Heart Logs. [https://bravenewgeek.com/you-cannot-have-exactly-once-delivery-redux/]