本篇是《Streaming Systems》第一章的总结输出。
在大数据领域,最近几年 Streaming data processing 变得越来越重要、越来越为人所知,下面是其中的一些原因:
- 商业对于实时性要求更高,而 streaming 是可以达到其低延迟目标的;
- 当前,数据量巨大、无限的数据集越来越普遍,原生就为无限流设计的系统更适合处理这种场景的数据;
- 实时地处理数据,将会使得资源负载更加均衡,其资源消耗也更可控(包括:可预测)。
当然 Streaming System 在开始的时候并不是那么成熟,特别是跟 batch system 对比。但是,现在 Streaming System 已经是非常成熟了,而业内对其的理解还停留在过去,很多人并没有真正理解 Streaming 的含义。
本篇文章主要聚焦以下几点:
- Terminology:对于 Streaming 做一个准确的定义;
- Capabilities:指出现有 Streaming System 的一些问题,并提出一些新的观点(系统设计者在设计时为了满足未来数据处理的需求应该考虑一下);
- Time Domains:介绍数据处理领域两个 time domain 的概念(process time 和 event time)。
1. What is Streaming?
什么是 Streaming?Streaming 这个词在今天应用得非常广泛,它可能会给 Streaming System 中的 Streaming 带来一些误导。Streaming 很长一段时间都跟 无限流、近似结果等概念联系在一起,这实际上模糊了 Streaming 的真正含义,那些概念仅限于过去对 Streaming 的描述(比如:近似结果),但是现在 Streaming 发展得已经很成熟了。如果 Streaming System 可以做到像 Batch System 在生产环境的准确性,那么 Streaming 将会是另外一种含义。
Streaming System:A type of data processing engine that is designed with infinite datasets in mind.
如果你想要表达 low-latency,approximate 或者 speculative results 的含义,最好直接使用它们,而不是用 Streaming 来表示。
1.1. 如何定义 dataset
关于dataset 的定义,从两个维度来说:cardinality 和 constitution。
cardinality 主要是关于 dataset 大小(或量级)的定义,可以分为:
- Bounded data:
A type of dataset that is finite in size
; - Unbounded data:
A type of dataset that is infinite in size
。
constitution 定义了与 dataset 交互的方式,可以分为:
- Table:
A holistic view of a dataset at a specific point in time. SQL systems have traditionally dealt in tables
(在某个特定的时间点上可以看到全部的数据); - Stream:
An element-by-element view of the evolution of a dataset over time. The MapReduce lineage of data processing systems have traditionally dealt in streams
(随着时间数据会有相应的变化)。
后面会详细讲述 Table 和 Stream 的内容,在这之前,重点会在 Stream 上,它现在已经是流和批的基础(batch 是一种特殊的 stream),也最能体现 Streaming Systems 面临的特有挑战。
1.2. Streaming 的局限性被夸大了
Streaming 过去一直被认为是一个可以提供 low-latency、inaccurate 或 speculative results 的服务,特别是在与 batch system 提供的准确性做对比之后,大家几乎不会把 Streaming 与强一致性、准确性联系在一起,比如最开始的 Lambda 架构。
Lambda 架构在当时提出了之后,取得了非常大的成功,在业内应用非常广泛,但其最大的缺点就是 —— 业务需要维护两套系统。Kreps 后来首先质疑了 Lambda 架构,接着又提出了 Kappa 架构。但是如果是作者的话,他会更加激进一些,直接提出:Streaming System 可以提供批功能的超集。
Batch System 的目标是高吞吐、节省资源,并针对批的场景做了大量的优化,并不是天生为无限流设计的。在 DataFlow 中,我们使用同一个模型做批和流的处理,针对不同的场景也做了相应具体的优化,虽然目前是运行不同的 Runner 中。
1.3. 一个 Streaming System 需要加强的地方
Streaming 的成熟发展,将使得 Lambda 架构变成历史,但 Streaming System 想要在批处理领域做得比 Batch System 更好,还需要在下面两个地方上加强。
1.3.1. Correctness
它的核心就是状态存储的一致性,需要有一个 checkpoint 机制来保证 state 的一致性。最开始是 Spark Streaming 提供了这样的机制,现在 Streaming System 从本质上已经有了很大的提高,强一致性已经成为 Streaming System 的必备要求(不能保证一致性的 Streaming System 未来必然是会被淘汰的)。
1.3.2. Tools for reasoning about time
对于无限、无序数据流的处理,需要 goods tools for reasoning about time(不太好翻译,理解就行,简单来说就是,关于 time 推理的定义,比如:应该怎么定义才能保证数据的完整性,一个窗口应该何时关闭?),这里先看下 time domain 的重要概念。
1.4. Process Time VS Event Time
关于 time domain 有两种类型:
- Event Time:
This is the time at which events actually occurred
; - Processing Time:
This is the time at which events are observed in the system
。
理想情况下,Process Time 和 Event Time 应该是相等的(如下图中那条虚线),但在实际情况下,它们之间差距的影响因素非常多,可能跟软件、硬件或数据有关,并且这个差异还是毫无规律可循的,如下图所示:
Time-Domain mappingProcess Time 和 Event Time 给 Streaming Processing 带来了很多的问题,由于 unbounded dataset 的无边界特性,这些系统会提供一些把输入数据源进行 window 操作的概念。window 操作的本质还是把无限流按时间切片,对于那些关注 Event Time 的应用来说,肯定是不能按照 Process Time 进行 window 操作的(Process Time 和 Event Time 之间的无关性会导致 window 之间的不准确性)。
之前的系统都依赖了【完整性】的概念,但如果把这个概念应用无限流上时就会有一些问题,假如在 window 中使用了 Event Time,那么应该如何定义数据的完整性呢?怎么决定什么时候拿到了 X (event time)之前的所有数据?与其想着如何去把无限流切片,不如我们思考一下:如何设计一种新的系统来适应这种不确定性?
2. Data Processing Patterns
这一节主要是关于 Bounded data 和 Unbounded data 处理的常见模式(优点类似于设计模式,但又不完全相同)。
2.1. Bounded Data
Bounded Data 的处理模型非常简单,比如:可以使用 MapReduce 去做。
Bounded Data processing with a classic batch engine2.2. Unbounded Data:Batch
先看下使用 Batch engine 去处理 Unbounded Data 的情况。
2.2.1. Fixed windows
处理模型简单来说就是微批处理(像 Spark Streaming 这种),这种模型依然会有完整性(Completeness)的问题,直到所有的数据都到了再进行处理?还是每当有新数据来,就把这个 window 的整个 batch 都重新计算一遍?
Unbounded data processing via ad hoc fixed windows with a classic batch engine2.2.2. Sessions
使用 Batch 引擎去处理 Session 类型的任务时,还是通过切分 batch 来做,如果 batch 太大,结果可能会带来相应的延迟;如果通过额外的逻辑把新的数据合并到之前的 session 窗口,又会带来非常大的复杂性。
Unbounded data processing into sessions via ad hoc fixed windows with a classic batch engine. An unbounded dataset is collected up front into finite, fixed-size windows of bounded data that are then subdivided into dynamic session windows via successive runs a of classic batch engine.2.3. Unbounded Data:Streaming
在现实中,对于 Unbounded Data,它不仅仅是无限流,还可能有以下特点:
- 对于 event time 而言,是强无序的,这意味着如果想根据 event time 做一些事情,还需要基于 event time 做一些 sort 操作;
- event time 的跨度非常大,很难假设在某个时间点大部分数据已经全部到了。
对于上面这种类型的数据源,有几种方案可以做相应的处理,这里详细介绍一下这些方法(跟具体的场景有关系)。
2.3.1. Time-agnostic
这种是最基本的场景,对时间不敏感(对 time 没有太大要求),下面举一些这种类型的例子。
2.3.1.2. Filtering
过滤是种比较简单的场景,在任何情况下,只依赖某一个元素(可能是多元素组合后的元素)进行过滤,在处理的时候,直接按照条件过滤即可,event-time 与 process-time 的偏差对其没什么影响。
Filtering unbounded data.2.3.1.2. Inner joins
Time-agnostic 的另一个常见场景就是 inner join 了。当对两个无限流数据源做 join 时,如果只关心两个数据源到达时 join 的结果,那么 time 就没有太大影响了(如果一个数据源的数据先到,先做缓存,但如果另一个数据源的数据一直不来,这时候可以引入 timeout 机制来解决这个问题)。
Performing an inner join on unbounded data.2.3.2. Approximation algorithms
近似算法,像:近似 Top-N、Streaming K-means 等等,在数据的处理时候,即使有时间上的倾斜(event-time 与 process-time 有偏差)对结果影响也不是很大。它的优点是:开销低+本身就是为无限流而设计;缺点是:数据规模的限制(已经完成的计算,很难再引入新到的数据),结果的近似性也限制了它们的应用。
Computing approximations on unbounded data.近似算法也有 time 的概念,只不过依赖的是 process time,即使使用了跨 event-time 的数据去训练它们,通常情况下意义也不大(本质上还是 time-agnostic 类型)。
2.3.3. Windowing
window 的类型有以下几种:
Windowing strategies.- Fixed Window:按时间切成固定大小的 window,是 aligned window 的一种;
- Sliding Window:也是一种 Fixed Window,但它有 fixed length 和 fixed period 两个设置;
- Sessions:一种 unaligned window,长度是未知的,一种动态的 window,比如分析用户的行为等。
window 在 process-time 和 event-time 下都是有意义的,这里分别来看下这两种情况。
Windowing by processing time
按 Process Time 切分 window 在实现上非常简单,只需要先缓存到来的数据,等到达到 process time 然后关闭窗口,做相应的计算即可。window 的完整性也很容易评估,因为我们知道 window 应该什么时候关闭(适合那些不需要 event-time 的场景,比如统计 qps、pv、uv 等)。
Windowing into fixed windows by processing time.这种方式最大的缺点就是,无法处理 event-time 相关的场景。而 Event Time 延迟的场景非常普遍,比如:手机 app 经常需要上报统计的信息,如果手机突然掉线几天,等在线之后,这时候上报的数据可能是几 hour /天前的数据。
Windowing by event time
对于需要保证 event-time 正确性的场景是使用 event-time window 的重要原因。
Windowing into fixed windows by event time.但是使用 vent-time window 并不是完全没有没有性能消耗的,它有两个明显的缺点:
- Buffering:相当于扩展了 window 的长度,需要缓存更多的数据(有些情况只需要增量缓存,并不缓存全部原始的数据,类似于先进行小范围的聚合);
- Completeness:一个 window 的完整性怎么定义?一个通用的解决方法就是使用 watermark 来去做,但是对于那些需要精确计算的场景(比如:计费)又该怎么做呢(后面的文章会介绍)?
3. 总结
本章主要讲述的内容:
- Streaming 的清晰定义,对于 dataset 两个维度的定义;
- 评估设计良好的 streaming 和 batch system,指出 streaming 是 batch 的超集,Lambda 架构提出的前提是 streaming system 的功能还比较弱;
- 提出两个重要的地方(如果 streaming system 想在 batch 领域赶上 batch system 的话):正确性和 Tools for reasoning about time;
- event-time 和 process-time 的差异;
- 当前对于 Bounded data 和 Unbounded data,常用的处理模式。
有误的地方,欢迎指正~
参考:
网友评论