大数据计算 Lambda架构 vs Kappa架构 到 Flink

Lambda 架构

Lambda 架构由Storm的作者Nathan Marz提出,其设计目的在于提供一个能满足大数据系统关键特性的架构,包括高容错、低延迟、可扩展等。其整合离线计算与实时计算,融合不可变性、读写分离和复杂性隔离等原则,可集成Hadoop, Kafka, Spark,Storm等各类大数据组件。
    Lambda 架构可分解为三层Layer,即Batch Layer, Real-Time(Speed) Layer和Serving Layer。
Batch Layer : 存储数据集,在数据集上预先计算查询函数,并构建查询所对应的View。Batch Layer可以很好的处理离线数据,但有很多场景数据是不断实时生成且需要实时查询处理,对于这情况, Speed Layer更为适合。
Speed Layer : Batch Layer处理的是全体数据集,而Speed Layer处理的是最近的增量数据流。Speed Layer为了效率,在接收到新的数据后会不断更新Real-time View,而Batch Layer是根据全体离线数据集直接得到Batch View。
Serving Layer : Serving Layer用于合并Batch View和Real-time View中的结果数据集到最终数据集。

Lambda架构主要由这几部分构成:数据源(Kafka),数据处理(Storm,Hadoop),服务数据库(Serving DB)。其中数据源和服务数据库是整个架构数据的入口和出口。数据处理则是分为在在线处理和离线处理两部分。

当数据通过kafka消息中间件,进入Lambda架构后,会同时进入离线处理(Hadoop)和实时处理(Storm)两个处理模块。离线处理进行批计算,将大量T+1的数据进行汇总。而实时处理则是进行流处理或者是微批处理,计算秒级、分钟级的结果。最后都录入到服务数据库(Serving DB)中进行汇总,暴露给上层服务调用。

Lambda架构的好处是:架构简单,很好的结合了离线批处理和实时流处理的优点,稳定且实时计算成本可控。

此外,它对数据订正也很友好。如果后期数据统计口径变更,重新运行离线任务,则可以很快的将历史数据订正为最新的口径。

然而,Lambda也有很多问题。

其中Jay Kreps认为最突出的问题就是需要同时维护实时处理和离线处理两套代码的同时还要保证两套处理结果保持一致。这无疑是非常让人头疼的。

一个典型的Lambda架构如下,

    这种架构主要面向的场景是逻辑比较复杂同时又希望延迟比较低的异步处理程序,比如搜索引擎、推荐引擎等。
    系统从一个流中读取被我们定义为不可变的数据,分别灌入实时系统如Storm和批处理系统如Hadoop,然后各自输出自己的结果,这些结果会在查询端进行合并。当然,这种系统也可有很多变种,比如上图中的Kafka也可替换成其他的分布式队列,Storm也可以替换成其他的流式计算引擎。

Kappa 架构

Kappa 架构是LinkedIn的Jay Kreps结合实际经验和个人体会,针对Lambda架构进行深度剖析,分析其优缺点并采用的替代方案。Lambda 架构的一个很明显的问题是需要维护两套分别跑在批处理和实时计算系统上面的代码,而且这两套代码得产出一模一样的结果。因此对于设计这类系统的人来讲,要面对的问题是:为什么我们不能改进流计算系统让它能处理这些问题?为什么不能让流系统来解决数据全量处理的问题?流计算天然的分布式特性注定其扩展性比较好,能否加大并发量来处理海量的历史数据?基于种种问题的考虑,Jay提出了Kappa这种替代方案。

那如何用流计算系统对全量数据进行重新计算,步骤如下:

    1、用Kafka或类似的分布式队列保存数据,需要几天数据量就保存几天。

    2、当需要全量计算时,重新起一个流计算实例,从头开始读取数据进行处理,并输出到一个结果存储中。

    3、当新的实例完成后,停止老的流计算实例,并把老的一引起结果删除。

一个典型的Kappa架构如下:

Kafka或者其他消息中间件,具备保留多日数据的能力。正常情况下kafka都是吐出实时数据,经过实时处理系统,进入服务数据库(Serving DB)。

当系统需要数据订正时,重放消息,修正实时处理代码,扩展实时处理系统的并发度,快速回溯过去历史数据。

这样的架构简单,避免了维护两套系统还需要保持结果一致的问题,也很好解决了数据订正问题。

但它也有它的问题:

1、消息中间件缓存的数据量和回溯数据有性能瓶颈。通常算法需要过去180天的数据,如果都存在消息中间件,无疑有非常大的压力。同时,一次性回溯订正180天级别的数据,对实时计算的资源消耗也非常大。

2、在实时数据处理时,遇到大量不同的实时流进行关联时,非常依赖实时计算系统的能力,很可能因为数据流先后顺序问题,导致数据丢失。

例如:一个消费者在淘宝网上搜索商品。正常来说,搜索结果里,商品曝光数据应该早于用户点击数据产出。然而因为可能会因为系统延迟,导致相同商品的曝光数据晚于点击数据进入实时处理系统。如果开发人员没意识到这样的问题,很可能会代码设计成曝光数据等待点击数据进行关联。关联不上曝光数据的点击数据就很容易被一些简单的条件判断语句抛弃。

对于离线处理来说,消息都是批处理,不存在关联不上的情况。在Lambda架构下,即使实时部分数据处理存在一定丢失,但因为离线数据占绝对优势,所以对整体结果影响很小。即使当天的实时处理结果存在问题,也会在第二天被离线处理的正确结果进行覆盖。保证了最终结果正确。

Flink

Lambda架构和Kappa架构的优缺点对比:

优点 缺点
Lambda 架构简单 实时、离线数据很难保持一致结果
很好的结合了离线批处理和实时流处理的优点 需要维护两套系统
稳定且实时计算成本可控
离线数据易于订正
Kappa 只需要维护实时处理模块 强依赖消息中间件缓存能力
可以通过消息重放 实时数据处理时存在丢失数据可能
无需离线实时数据合并

Kappa在抛弃了离线数据处理模块的时候,同时抛弃了离线计算更加稳定可靠的特点。Lambda虽然保证了离线计算的稳定性,但双系统的维护成本高且两套代码带来后期运维困难。

为了实现流批处理一体化,Blink采用的将流处理视为批处理的一种特殊形式。因此在内部维持了若干张张流表。通过缓存时间进行约束,限定在一个时间段内的数据组成的表,从而将实时流转为微批处理。

理论上只要把时间窗口开的足够大,Flink的流表可以存下上百日的数据,从而保证微批处理的“微”足够大可以替换掉离线处理数据。

但这样做存在几个问题:

1.Flink的流表是放在内存中,不做持久化处理的。一旦任务发生异常,内存数据丢失,Flink是需要回溯上游消息流,从而转为Kappa的结构。

2.数据窗口开的越大,内存成本越高。受限于成本,对大量数据处理仍然有可支持的物理空间上限。

3.下游接收的通常都是处理结果,对于内存中的流表数据是无法直接访问的。这样无形中增加了开发成本。