Samza 与 Storm
人们通常想知道类似的系统如何比较。我们已尽全力将 Samza 的功能集与其他系统进行对比。但是我们不是这些框架的专家,当然我们也是完全有偏见的。如果我们有任何东西,请让我们知道,我们会纠正。
Storm 和 Samza 是相当相似的。两个系统提供了许多相同的高级功能:分区流模型,分布式执行环境,流处理 API,容错,卡夫卡集成等。
Storm 和 Samza 对于类似的概念使用不同的单词:Storm 中的喷口类似于 Samza 中的流消费者,螺栓类似于任务,元组类似于 Samza 中的消息。一些额外的构建块,如三叉戟,拓扑等,在 Samza 中没有直接的等价物。
分类和保证
Storm允许您选择要处理邮件的保证级别:
- 最简单的模式是一次性传递,如果处理不正确,或者执行处理的机器失败,则会丢弃消息。此模式不需要特殊逻辑,并按照它们由喷口生成的顺序处理消息。
- 还有至少一次传递,它跟踪每个输入元组(以及其生成的任何下游元组)是否在配置的超时内成功处理,通过保留所有发出的元组的内存中记录。在超时期间未完全处理的任何元组都将由喷口重新发出。这意味着螺栓可能会多次看到相同的元组,并且该消息可以被无序处理。该机制还需要用户代码的一些合作,用户代码必须维护记录的祖先,以便适当地确认其输入。这在Storm 的维基上有深入的解释。
- 最后,Storm 使用其 Trident 抽象提供了一次性的语义。该模式使用与至少一次模式相同的故障检测机制。元组实际上至少处理了一次,但是 Storm 的状态实现允许检测和忽略重复数据。(重复检测仅适用于由 Storm 管理的状态,如果您的代码具有其他副作用,例如向拓扑之外的服务发送消息,则不会具有完全一次的语义。)在此模式下,输入流批量,并按严格顺序处理批次。
Samza 还提供保证交货 - 目前仅交货至少一次,但计划支持一次性语义。在每个流分区中,Samza 总是按照它们在分区中显示的顺序来处理消息,但不能保证在不同的输入流或分区之间进行排序。该模型允许 Samza 至少提供一次,而不需要祖先跟踪的开销。在 Samza,使用最多的一次交付(即丢弃消息失败)将不会有性能优势,这就是为什么我们不提供这种模式 - 消息传递总是得到保证。
此外,由于 Samza 从未在分区无序处理消息,所以更适合处理密钥数据。例如,如果您有一个数据库更新流 - 以后的更新可能会替代以前的更新,那么重新排序消息可能会改变最终结果。如果同一个密钥的所有更新显示在同一流分区中,则 Samza 能够保证一致的状态。
状态管理
Storm 的较低级别的 API 不支持在流过程中管理状态。螺栓可以保持内存状态(如果螺栓死了,则会丢失),或者可以调用远程数据库来读取和写入状态。然而,拓扑通常可以以比可以进行远程数据库的调用更高的速率来处理消息,因此对每个消息的远程调用迅速成为瓶颈。
作为其更高级别 Trident API 的一部分,Storm 提供自动状态管理。它将状态保存在内存中,并定期检查它到远程数据库(例如 Cassandra)以获得持久性,因此远程数据库调用的成本在多个处理的元组中进行分摊。通过在状态旁边维护元数据,Trident 能够实现一次处理语义 - 例如,如果您计算事件,该机制允许计数器正确,即使机器故障并且元组被重播。
如果每个螺栓的状态数量相当小 - 也许小于100kB,Storm 的缓存和批处理状态变化的方法效果很好。这使得它适合于跟踪计数器,度量的最小值,最大值和平均值等。但是,如果您需要维护大量的状态,则这种方法本质上会降低到每个处理的元组进行数据库调用,以及相关的性能成本。
萨马对国家管理采取了完全不同的做法。每个 Samza 任务都不包括使用远程数据库进行持久存储,而是包含位于同一机器上的嵌入式键值存储。即使当商店的内容大于可用内存时,对此商店的读写也非常快。对此键值存储的更改将复制到集群中的其他计算机,以便如果一台计算机已停止,则其运行的任务的状态可以在另一台计算机上恢复。
通过在同一台机器上共存存储和处理,即使有大量的状态,Samza 也能够实现非常高的吞吐量。如果要执行不仅仅是计数器的有状态操作,这是必要的。例如,如果要执行多个流的窗口连接,或者使用数据库表(通过更改日志复制到Samza)加入流,或将多个相关消息分组到更大的消息中,则需要保持这么多状态将状态保持在本地的任务更为有效。
Samza 的状态处理的局限性在于它目前不支持一次性语义 - 现在至少支持一次。但是我们正在努力修复这个问题,请随时关注更新。
分区和并行性
风暴的并行模式与 Samza 相似。两种框架将处理分解成可以并行运行的独立任务。资源分配独立于任务数量:一个小工作可以将单个进程中的所有任务保存在单个计算机上; 大量工作可以在许多机器上将任务分散在许多过程中。
最大的区别是 Storm 在默认情况下每个任务使用一个线程,而 Samza 使用单线程进程(容器)。Samza 容器可能包含多个任务,但只有一个线程依次调用每个任务。这意味着每个容器映射到一个 CPU 核心,这使得资源模型更简单,并减少了在同一台机器上运行的其他任务的干扰。Storm 的多线程模型的优点是可以以较不可预测的资源模型为代价,更好地利用空闲机器上的多余容量。
Storm 支持动态重新平衡,这意味着向拓扑添加更多的线程或进程,而无需重新启动拓扑或集群。这是一个方便的功能,特别是在开发过程中。我们没有把它添加到 Samza:在哲学上,我们认为这种变化应该经历一个正常的配置管理过程(即版本控制,通知等),因为它会影响生产性能。换句话说,作业的代码和配置应该完全重新创建集群的状态。
当使用具有 Trident 的事务性喷嘴(实现一次语义的要求)时,并行性可能会降低。Trident 依赖于其输入流中的全局排序,即排序流的所有分区,而不仅仅是在一个分区内。这意味着拓扑的输入流必须经过单个喷口实例,有效地忽略了输入流的划分。这个喷口可能成为大容量流的瓶颈。在 Samza,所有的流处理是平行的 - 没有这样的阻塞点。
部署和执行
Storm 集群由运行 Supervisor 守护程序的一组节点组成。主管守护进程与运行名为 Nimbus 守护进程的单个主节点进行通信。Nimbus 守护进程负责在集群中分配工作和管理资源。有关详细信息,请参阅 Storm's Tutorial 页面。这与 YARN 非常相似;尽管 YARN 有一些更加全面的特征,旨在成为多框架,Nimbus 更好地与 Storm 集成。
雅虎 还发布了Storm-YARN。如这个雅虎 博客文章 所述,Storm-YARN 是一个封装,在 YARN 网格内启动了一个单一的 Storm 集群(与 Nimbus 和 Supervisors 完成)。
Storm 的 Nimbus 和 YARN 的 ResourceManager 之间以及 Storm 的主管和 YARN 的节点管理器之间有很多相似之处。作为 YARN 生态系统中一流的公民,Samza 应该直接使用YARN,而不是编写自己的资源管理框架,或在 YARN 内部运行第二个资源管理框架。YARN 稳定,采用,功能齐全,可与 Hadoop 进行互操作。它还提供了一些很好的功能,如安全性(用户验证),cgroup 进程隔离等。
Samza 的 YARN 支持是可插拔的,因此如果愿意,您可以将其交换为不同的执行框架。
语言支持
Storm 是用 Java 和 Clojure 编写的,但对非 JVM 语言有很好的支持。它遵循类似于 MapReduce Streaming 的模型:非 JVM 任务在单独的进程中启动,数据被发送到其 stdin,并且从其 stdout 读取输出。
Samza 是用 Java 和 Scala 编写的。它是以多语言支持构建的,但目前只支持 JVM 语言。
工作流程
Storm 提供了代码中拓扑的建模(多个阶段的处理图)。Trident 还提供了一个更高级别的API,包括熟悉的关系类运算符,如过滤器,分组,聚合和连接。这意味着整个拓扑结构在一个地方被连线,这具有代码中记录的优点,但是缺点是整个拓扑需要作为一个整体来开发和部署。
在萨姆萨,每个工作都是一个独立的实体。您可以在单个代码库中定义多个作业,也可以使用不同的代码库,使用不同的工作组来处理不同的作业。每个作业都被单独部署,启动和停止。作业仅通过命名流进行通信,您可以将作业添加到系统中,而不会影响任何其他作业。这使得 Samza 非常适合处理大型公司的数据流。
Samza 的方法可以在 Storm 中通过代理(如 Kafka )连接两个独立的拓扑来模拟。然而,Storm 的完全一次语义的实现只能在单个拓扑中起作用。
成熟度
我们不能说 Storm 的成熟度,但是它拥有令人印象深刻的采纳者,强大的功能,似乎正在积极发展。它与许多常见的消息系统(RabbitMQ,Kestrel,Kafka等)很好地集成。
虽然 Samza 建立在固体组件上,但是相当不成熟。YARN 是相当新的,但已经在雅虎的3000多个节点集群上运行,该项目正在由 Hortonworks 和 Cloudera 积极开发。Kafka 拥有强大的页面,近期日益普及。它也经常用于 Storm。Samza 是在 LinkedIn 中使用的全新项目。我们的希望是别人会觉得有用,也可以采纳。
缓冲和延迟
Storm 使用 ZeroMQ 进行螺栓之间的非持久通信,从而实现了极少延迟的元组传输。Samza 没有等效的机制,并且总是将任务输出写入流。
另一方面,当一个螺栓尝试使用 ZeroMQ 发送消息,并且消费者不能足够快地读取消息时,生产者流程中的 ZeroMQ 缓冲区开始填满消息。如果此缓冲区增长太多,则可能会达到拓扑的处理超时,从而导致消息在喷口处重新发出,并通过向缓冲区添加更多消息使问题更糟。为了防止这种溢出,您可以随时在拓扑中配置最多可能在飞行中的消息; 当达到该阈值时,喷口阻塞,直到飞行中的某些消息被完全处理。这种机制允许背压,但需要仔细配置拓扑。如果拓扑中的单个螺栓开始运行缓慢,
在尝试处理容错和消息传递语义时,螺栓之间缺乏经纪人也增加了复杂性。Storm 具有检测未被处理的元组的聪明机制,但 Samza 不需要这样的机制,因为每个输入和输出流都是容错和复制的。
Samza 采取不同的缓冲方法。我们在 StreamTask 之间的每一跳缓冲到磁盘。比较介绍页面详细描述了这一决定及其权衡。这种设计决策使得耐久性保证容易,并且具有允许缓冲器在其处理中已经落后的情况下吸收大量积压的消息的优点。然而,它的延迟稍微更高的代价。
如上面的工作流程部分所述,Samza 的方法可以在 Storm 中模拟,但功能上会丢失。
隔离
Storm 提供标准的 UNIX 进程级隔离。如果使用太多的 CPU,磁盘,网络或内存,您的拓扑可能会影响另一个拓扑的性能(反之亦然)。
Samza 依靠 YARN 提供资源级隔离。目前,YARN 为内存和 CPU 限制(通过cgroups)提供了明确的控制,并且都已经成功地与 Samza 一起使用。目前,YARN 不提供磁盘或网络的隔离。
分布式RPC
在风暴中,您可以编写不仅接受固定事件流的拓扑,还可以让客户端按需运行分布式计算。该查询作为特殊口上的元组发送到拓扑中,当拓扑计算出答案时,它将返回给客户端(谁同步等待答案)。该工具称为分布式RPC(DRPC)。
Samza 目前没有与 DRPC 相同的 API,但您可以使用 Samza 的流处理原语自行构建它。
数据模型
Storm 将所有消息作为具有定义的数据模型的元组,但是可插入序列化。
Samza 的序列化和数据模型都是可插拔的。我们对于哪种方法是最好的并不是非常愚蠢的。
更多建议: