Flink介绍——实时计算核心论文之S4论文总结

发布于:2025-04-03 ⋅ 阅读:(15) ⋅ 点赞:(0)

PE对象的构成与功能

我们先来看下S4是怎么抽象流式计算的。

S4将所有的计算过程抽象为一个个Processing Element(处理元素)对象,简称为PE对象。

每一个PE对象,都有四部分组成,分别是:

  • 功能(Functionality):PE对象的核心是其功能实现,这体现在类中定义的业务逻辑函数以及为该类配置的参数。

  • 事件类型(types of events):PE能够处理的事件类型,决定了它能接收和处理哪些类型的事件。

  • 事件的键(keyed attribute):PE能够处理的事件的键,用于事件的路由和分发。

  • 事件的键对应的值(value):PE处理的事件的键对应的值,用于事件的具体处理逻辑。

流式计算的逻辑模型

这些PE对象会组成一个有向无环图(DAG)。

DAG的起点是一些特殊的无键PE对象,它们负责接收外部发送来的事件流,这些外部发送过来的事件流,其实就是一条条的消息。

而这些无键PE会解析对应的消息,变成一个个事件。然后给每个事件打上事件类型、事件的Key和事件的Value三个信息,然后将事件发送出去。

接着下游的其他PE对象会根据自己定义的事件类型和能处理的键来接收对应的消息,并进行处理。如果系统中没有对应的键的PE,系统会创建新的PE对象。处理数据的PE对象可以选择处理完后立刻发送新的事件,或者在内部维护状态,处理一定数量的消息或经过固定时间间隔后发送消息。

最后在DAG的终点,是一系列负责发布(Publish)最终计算结果的PE对象。这些对象可以设置发布的频率,如每收到一个事件就发送,或者在接收到一定数量的事件或经过特定时间间隔后发送。

这么来描述,可能整个过程有点过于抽象,我们还是来一起看一看论文里图一的示例。这个例子,是用来统计整个系统里,出现得最多的K个单词,也就是Top K,它的整个DAG的结构是这样的:

  • 首先,在DAG的起始节点,是一个 QuoteSplitterPE,这个PE也是一个无键PE。

    • 它负责接收外部发送来的句子,然后分割成一个个单词,接着会统计单词在句子里面出现的次数。

    • 然后,这个PE会把每个单词的出现次数,作为一个WordEvent发送出去。对应的Event的Key就是(Word,具体单词)的这么一个组合(Tuple)。而对应的Event的值,就是(Count,出现次数)的这么一个组合(Tuple)。

  • 第二层里,是一系列叫做 WordCountPE 的PE对象。它在系统里面申明,我只接收WordEvent。然后每个不同的单词,都会有一个对应的PE对象。所以可以想象,整个系统中会有海量的PE对象。

    • 它的逻辑也很简单,上游的PE,会把相同单词的WordEvent都发送到同一个PE,那么这个PE里,就可以统计到这个单词出现的总的次数。

    • 每当收到一个事件,这个单词的出现次数就会更新,对应的它就会向下游,发送一个UpdatedCountEvent,也就是更新单词计数的事件。

    • 这个事件里,对应的Key是(Sort,N)这样一个组合,每一个PE对象里的N都是随机的,但是固定不变的。这个组合是为了下一层的负载均衡,我们可以自己去设定N这个参数,N越大,意味着下游的PE对象越多,负载就会分配到更多不同的对象里去计算的。而对应的值,则包括了对应的单词是什么,以及对应的单词的出现次数。也就是((Word,具体单词), (Count,出现次数)) 这么一个组合。

  • 第三层里,则是一系列叫做 SortPE 的对象。它的作用则是接收上游不同单词的出现次数,然后在内部进行排序。最后输出自己内部排序的Top K,再给到下游。本质上,它相当于是所有单词的某一个分区的数据。这个分区,包含了一部分单词的所有数据。我们前面设定了N是几,我们就会有几个SortPE的对象。

    • 给到下游的事件,叫做PartialTopkEvent,看名字你就知道它包含的信息,就是一个部分数据的Top K。

    • 所有SortPE的对象,输出的消息的Key都是相同的,因为为了获得全局的排序,它们需要发送给同一个PE对象。在这里,这个Key就被写死成了(topk,1234) 这么一个组合。而Value,则是K个(单词,出现次数)的集合。

  • 而整个DAG的终点,则是唯一的一个 MergePE。它的作用,就是接收PartialTopkEvent,然后在内部进行一次归并,选出全局的TopK。并且最终,它还需要把对应的数据,写入到外部其他的存储系统,比如数据库里,供其他的应用读取。

S4这个把整个数据处理流程,变成一个有向无环图的设计,也是后续所有流式处理系统都采用的一个解决方案。所有的数据,变成了事件流,而开发人员只需要做两件事情:

  • 第一,是设计整个DAG应该是什么样子的。

  • 第二,是实现这个当中每一个节点的业务逻辑代码。

而开发人员,不需要关心数据是在哪里被处理的。这些底层处理都由S4来负责。

抽象计算模型的设计思路

其实S4的计算模型设计思路,和我们之前看过的HDFS、MapReduce 等框架类似。PE其实和Map/Reduce函数一样,只是一个抽象的概念。不过S4的系统设计,要更加激进一点,那就是 S4选择了一个无中心的,完全对称的架构。

S4 没有所谓的Master节点,如果一定要说有一个中心化的地方的话,S4依赖于Zookeeper,也就是一个类似于Chubby这样的分布式锁系统。S4的所有服务器,都会作为一个处理节点PN(ProcessingNode),注册在Zookeeper上。具体如何分配负载,是由各个节点协商决定的,而不是由一个中心化的Master统一分配。

每一个处理节点,都是相同的,它由上下两部分组成。

上面部分,是实际的业务处理逻辑模块:

  • 它通过Event Listener,监听外部发送过来的消息,转发给对应的PE对象。

  • PE对象的所有输出结果,都发送给Dispatcher,让Dispatcher确定应该发送给哪些PE里。

  • 实际的消息发送,会由Dispatcher交给Emitter,对外发送出去。

业务处理模块里,只会确定对应的消息发送,应该发送给哪一个逻辑上的PE,实际具体发送到哪一台物理节点,则是由下面的通信层模块来决定的。

这个模块主要解决这样几个问题:

  • 首先是具体的路由,也就是Event要去的某一个逻辑PE,到底在哪台物理服务器上,是由通信层模块来找到并且发送出去的,上层的业务处理流程不需要知道。

  • 其次是负载均衡,不同的单词,更新的频率可能不一样。所以不同的处理节点的负载也会不一样。当有一个新的单词出现的时候,我们需要判断新的PE应该放到哪一个节点上去。

  • 然后就是底层的容错恢复机制了,当有特定节点挂掉的时候,我们需要在其他的节点上,恢复原先这个节点被分配的PE。

  • 最后就是实际的传输协议,S4是一个“插件式”的架构,也就是底层的传输协议也是可以切换的。S4既支持通过TCP发送消息,确保消息能够发送成功,也支持通过UDP发送消息,来支持更大的吞吐量。

这种屏蔽了底层复杂实现,提供抽象出简单的计算模型供用户以更低的门槛去使用的思路特别常见,在S4框架中,开发人员只需要关注PE这个纯粹的业务逻辑层面。至于计算在哪一台服务器上发生,各个节点之间是怎么通信的,开发人员完全不需要关心。

S4的局限

S4虽然在流式计算领域迈出了重要的一步,但其设计上的不足也暴露了它在实际应用中的局限性。这些问题为后续流式数据处理系统的改进提供了方向,推动了该领域的进一步发展。

1. 海量对象的问题

S4的设计中,每个处理数据的Key都需要一个独立的对象。这种设计虽然能够灵活地处理不同的Key,但也导致了系统中存在海量的对象。一个Key如果只出现一次,之后再也不出现,也会占用内存。

为了解决这个问题,S4引入了TTL(Time to Live)机制,定期清理掉不再需要的Key,从而释放内存资源。

2. 缺乏时间窗口的概念

在实时数据处理中,时间窗口是一个非常重要的概念,例如统计“过去五分钟的下单量”或“过去一小时的完单量”,这样有一个时间范围的数据。然而,S4的设计中并没有内置时间窗口的概念。这意味着开发者需要在PE(Processing Element)的代码中自行维护或实现时间窗口逻辑,这显著增加了开发的复杂度和难度。

3. 容错处理的不足

S4的容错机制过于简单。当某个计算节点挂掉时,系统就重新启动一个新的节点来承担其工作。然而,原先节点中PE维护的状态信息会丢失,这意味着系统无法知道当前的统计信息或处理到哪些事件。对应的解决方案是退回到离线批处理数据,但这显然违背了流式处理的初衷,只能作为一种权宜之计。

4. 不支持动态扩容

S4作为一个分布式系统,却不支持真正的动态扩容。在论文的假设中,S4假设运行中的集群不会增加或减少节点。这意味着当负载快速上升时,S4的策略是随机丢弃一些数据,而不是通过增加硬件来解决问题。这种策略本质上是对数据进行了采样,而不是真正通过扩展资源来应对负载变化。

总结

S4的设计为大数据的流式处理迈出了重要的一步,但其存在的问题也为后续流式数据处理系统的改进提供了方向。后续的流式计算框架如Storm、Kafka、Flink等,在借鉴S4优点的基础上,对上述问题进行了优化和改进,推动了流式计算技术的进一步发展。

下面我们梳理一下针对S4的论文总结出来的优缺点:

S4框架的优点

  • 实时性:S4能够进行低延时的“实时”数据处理,满足了业务对实时数据反馈的需求,如Yahoo通过S4及时获取广告和搜索数据的反馈,以及进行在线的A/B测试。

  • 易用性:开发人员只需实现Processing Element(PE)的业务处理逻辑,无需关心分布式系统的底层细节,如数据分发、计算节点调度及容错恢复等,降低了开发门槛。

  • 灵活性:S4借鉴了MapReduce和Actors Model,结合了两者的优点,实现了更灵活和高效的数据处理。

  • 高效处理机制:S4大量使用本地内存而非磁盘IO,提高了数据处理速度,满足了实时性要求。

S4框架的不足

  • 海量对象问题:每个处理数据的Key都需要一个独立的对象,导致系统中存在海量的对象,增加了内存占用。S4通过给Key设定TTL,定期清理掉不再需要的Key来缓解这个问题。

  • 缺乏时间窗口概念:S4没有内置时间窗口的概念,无法直接满足如“过去一分钟的热搜”等有时间范围的统计需求,开发者需自行在PE代码中维护或实现时间窗口逻辑,增加了开发难度。

  • 容错处理简单:S4的容错机制仅能在计算节点挂掉时重新启动新节点承担工作,但原先节点中PE维护的状态信息会丢失,且对节点间的数据传输没有全链路的传输保障。

  • 不支持动态扩容:S4不支持真正的动态扩容,在负载快速上升时,其策略是随机丢弃一些数据而非通过增加硬件来解决问题。


网站公告

今日签到

点亮在社区的每一天
去签到