Samza 与 Spark Streaming
Spark Streaming
人们通常想知道类似的系统如何比较。我们已尽全力将Samza的功能集与其他系统进行对比。但是我们不是这些框架的专家,当然我们也是完全有偏见的。如果我们有任何东西,请让我们知道,我们会纠正。
本概述正在比较 Spark Streaming 1.3.1 和 Samza 0.9.0。未来的版本可能会有变化。
Spark Streaming 是使用核心 Apache Spark API 的流处理系统。Samza 和 Spark Streaming 都提供数据一致性,容错性,编程 API 等。Spark 的流媒体方式与 Samza 不同。Samza处理收到的消息,而 Spark Streaming 将流视为一系列确定性批处理操作。Spark Streaming 将流分组为固定持续时间(如1秒)的批次。每个批处理都表示为弹性分布式数据集(RDD)。这些 RDD 的渐进序列称为离散化流(DStream)。
Spark Streaming 概述
在进行比较之前,以下是 Spark Streaming 应用程序的简要概述。如果您已经熟悉 Spark Streaming,您可以跳过此部分。Spark Streaming 应用程序有两个主要部分:数据接收和数据处理。
- 数据接收由接收器接收数据,并在 Spark 中存储数据(此时不在 RDD 中)。他们在1.3版本中对 Kafka 进行了非接收方式的实验。
- 数据处理将存储在 Spark 中的数据传输到 DStream 中。然后,您可以在 DStream 上应用两个操作 - 转换和输出操作。由于流式传输环境,DStream 的操作与一般 Spark RDD 有所不同。
以下是 Spark Streaming 部署的概述。Spark 有一个 SparkContext(在 SparkStreaming 中,它在驱动程序中被称为StreamingContext对象,SparkContext 与集群管理器(例如YARN,Mesos)交谈,然后为 Spark 应用程序分配资源(即执行程序),执行程序将运行任务通过 SparkContext,在 YARN 的上下文中,一个执行器相当于一个容器,任务是容器中运行的,驱动程序在提交作业(客户端模式)或应用程序管理器(客户端模式)的客户机中运行,集群模式),数据接收和数据处理都是执行器的任务,一个接收器(接收一个输入流)是一个长期运行的任务。处理有一堆任务。所有的任务都将发送给可用的执行者。
消息的排序
Spark Streaming 保证在一个 DStream 中对 RDD 的有序处理。由于每个 RDD 并行处理,所以在 RDD 内没有保证的顺序。这是 Spark 做的一个权衡设计。如果要在 RDD 中按顺序处理消息,则必须在一个线程中处理它们,这不具有并行性的好处。
Samza 保证按照它们在流的分区中显示的顺序来处理消息。Samza 还允许您使用 MessageChooser 定义分区之间的消息的确定性排序。
容错语义
Spark Streaming 对于不同的数据源具有不同的容错语义。在这里,为了更好的比较,只讨论使用 Spark Streaming 与 Kafka 时的语义。在 Spark 1.2中,Spark Streaming 在接收端提供了至少一次语义。在 Spark 1.3中,它采用无接收方式,这提供了一些好处。但是,它仍然不能保证输出动作的一次性语义。因为副作用的输出操作可能在作业失败时重复,并从检查点恢复。如果您的输出操作中的更新不是幂等或事务性的(例如发送到 Kafka 主题的消息),您将获得重复的消息。不要被 Spark Streaming 指南中的“一次性语义”所困惑。
Samza 提供了至少一次的邮件传递保证。当作业发生故障时,它重新启动容器并从检查点读取最新的偏移。当 Samza 的工作从故障中恢复时,它可能会多次处理一些数据。这是因为作业在最后一个检查点重新启动,并且在该检查点和故障之间已处理的任何消息将再次被处理。可以通过设置小的检查点间隔周期来最小化再处理数据的数量。
如果您可以确保幂等更新或事务更新, Spark Streaming 和 Samza 都可以实现端到端的一次性语义。该链接指向 Spark Streaming 页面,同样的想法也适用于 Samza。
状态管理
Spark Streaming 提供一个状态 DStream,它保持每个键的状态和一个称为 updateStateByKey 的转换操作来突变状态。每当应用 updateStateByKey 时,您将获得一个新状态DStream,其中所有状态都通过应用传递给 updateStateByKey 的函数进行更新。这种转换可以作为基本的键值存储,尽管它有一些缺点:
- 您只能将 DStream 操作应用到您的状态,因为它基本上是一个 DStream。
- 不提供对数据的任何键值访问。如果要访问某个键值,则需要遍历整个 DStream。
- 当状态较大时,由于每次处理新批次时,Spark Streaming 会消耗整个状态 DStream 来更新相关的键和值,因此效率低下。
Spark Streaming 定期将状态操作(updateStateByKey 和基于窗口的操作)的媒体数据写入 HDFS。在 updateStateByKey 的情况下,在每个检查点间隔之后,将整个状态 RDD 写入HDFS。正如我们在带有检查点的内存状态中提到的,当状态变大时,将整个状态写入持久存储是非常昂贵的。
Samza 使用嵌入式键值存储进行状态管理。这个商店被复制,因为它是突变的,并支持非常高的吞吐量写入和阅读。并且它给你很大的灵活性来决定你想要保持什么样的状态。更重要的是,您还可以插入其他存储引擎,从而在您可以使用的流处理算法中实现极大的灵活性。在这里可以找到不同类型的国家经理方法的良好比较。
状态管理的常见用例之一是流式流连接。虽然星火流有加入操作,该操作仅将两个批次是在相同的时间间隔。它不处理两个流中的事件不匹配的情况。Spark Streaming 的updateStateByKey 存储不匹配事件的方法也有一个限制,因为如果不匹配事件的数量很大,会有一个很大的状态,这会导致 Spark Streaming 中的无效。虽然 Samza 没有这个限制。
分区和并行性
Spark Streaming的并行性是通过将工作分解成小任务并将其发送给执行者而实现的。在Spark Streaming中有两种并行性:在并行处理流中并行化并行处理流:*在接收端,一个输入DStream 创建一个接收器,一个接收器接收一个输入数据流并作为长时间运行,运行任务 因此,为了并行化接收过程,您可以根据某些条件将一个输入流分解成多个输入流(例如,如果您正在接收一些分区的 Kafka 流,则可以根据分区拆分此流)。然后,您可以为这些流创建多个输入 DStream(因此多个接收器),并且接收器将作为多个任务运行。因此,您应该通过增加执行人员的核心数量或增加更多的执行人员来提供足够的资源。然后,如果需要,您可以在处理过程中将所有输入的 Dstream 组合成一个 DStream。在 Spark 1.3 中,Spark Streaming + Kafka Integration 正在使用无接收方式(directsream)。Spark Streaming 创建一个 RDD,其分区映射到 Kafka 分区是一对一的。这简化了接收机侧的并行性。*在处理方面,由于DStream是RDD的连续序列,所以通过正常的RDD操作(如map,reduceByKey,reduceByWindow)可以简单地实现并行。Spark Streaming + Kafka Integration 正在使用无接收器方法(称为directSream)。Spark Streaming 创建一个RDD,其分区映射到Kafka分区是一对一的。这简化了接收机侧的并行性。*在处理方面,由于DStream是RDD的连续序列,所以通过正常的RDD操作(如map,reduceByKey,reduceByWindow)可以简单地实现并行。Spark Streaming + Kafka Integration 正在使用无接收器方法(称为 directSream)。Spark Streaming 创建一个 RDD,其分区映射到 Kafka 分区是一对一的。这简化了接收机侧的并行性。*在处理方面,由于DStream是RDD的连续序列,所以通过正常的RDD操作(如map,reduceByKey,reduceByWindow)可以简单地实现并行。
Samza 的并行性是通过将处理分解成可并行化的独立任务来实现的。您可以在一个容器中运行多个任务,或者每个容器只运行一个任务。这取决于您的工作负载和延迟要求。例如,如果要快速重新处理流,则可以将容器的数量增加到每个容器一个任务。重要的是注意到一个容器只使用一个线程,它映射到一个 CPU。该 设计尝试简化资源管理和作业之间的隔离。
在 Samza 中,您可以灵活地定义一个任务所包含的内容。例如,在 Kafka 用例中,默认情况下,Samza 将具有相同分区 ID 的分区分组到一个任务中。这允许不同流之间的容易连接。开箱即用,Samza 还提供了将一个分区分配给一个任务的分组策略。这提供了可以使用多少个容器来处理这些输入流的最大可扩展性,并且适用于不需要输入流分组的非常高容量的作业。
缓冲和延迟
Spark 流主要是一系列小批处理。使用快速执行引擎,它可以达到低至1秒的延迟(从他们的论文)。从他们的页面,“块间隔的推荐最小值约为50 ms,低于此值的任务启动开销可能是一个问题。
如果处理速度比接收速度慢,则数据将作为内存中的 DStream 排队,队列将不断增加。为了运行健康的 Spark 流应用程序,系统应该被调整,直到处理速度与接收速度一样快。
使用 Apache Kafka 运行时,Samza作业可能会在低毫秒内延迟。它具有不同的缓冲方法。缓冲机制取决于输入和输出系统。例如,当使用 Kafka 作为输入和输出系统时,数据实际上被缓冲到磁盘。这种设计决定,通过牺牲一点延迟,允许缓冲区在工作落后于其处理时吸收大量积压的消息。
容错
Spark Streaming 和 Samza 中有两种故障:Spark Streaming 中的工作节点(运行执行程序)故障(相当于 Samza 中的容器故障)和驱动程序节点(运行驱动程序)故障(相当于应用程序管理器(AM))失败 Samza)。
当 Spark Streaming 中的工作节点出现故障时,集群管理器将重新启动它。当 Samza 中的容器发生故障时,应用程序管理器将与 YARN 一起启动新的容器。当 Spark Streaming 中的驱动程序节点出现故障时,YARN / Mesos / Spark Standalone 将自动重新启动驱动程序节点。Spark Streaming 可以使用 HDFS 中的检查点重新创建 StreamingContext。
在萨姆萨,YARN 负责处理容错。当 Samza 的 AM 失败时,YARN 将处理重新启动 AM。如果 AM 重新启动,Samza 将重新启动所有的容器。当集装箱发生故障时,AM 将打开一个新的集装箱。
部署和执行
Spark 有一个 SparkContext 对象与群集管理器通信,然后为应用程序分配资源。目前,Spark 支持三种类型的集群管理器:Spark独立,Apache Mesos和Hadoop YARN。除此之外,Spark 还有一个用于在 Amazon EC2 中启动的脚本。
Samza 目前支持 YARN 和本地执行。还有 Mesos 支持正在整合。
隔离
Spark Streaming 和 Samza 有相同的隔离。Spark Streaming 取决于集群管理器(例如 Mesos 或 YARN),Samza 依靠 YARN / Mesos 来提供处理器隔离。不同的应用程序在不同的JVM 中运行。除非写入外部存储器,否则数据不能在不同应用程序之间共享。由于 Samza 提供开箱即用的 Kafka 集成,因此很容易重用其他 Samza 作业的输出(见这里)。
语言支持
Spark Streaming 是用 Java 和 Scala 编写的,它提供 Scala,Java 和 Python API。
Samza 是用 Java 和 Scala 编写的,并且有一个 Java API。
工作流程
在 Spark Streaming 中,您将使用 DSL API 构建整个处理图,并将整个图形部署为一个单元。该图中的节点之间的通信(以 DStreams 的形式)由框架提供。那就像风暴一样。Samza 是完全不同的 - 每个工作只是一个消息处理器,并且没有框架支持拓扑。处理任务的输出总是需要返回到消息代理(例如 Kafka)。
Samza 设计的一个积极的后果是,工作的产出可以被多个不相关的工作所消耗,这些工作可能由不同的团队运行,而这些工作通过 Kafka 的缓冲来相互隔离。Storm 和 Spark Streaming 的框架内部流并不是这样。
虽然 Storm / Spark Streaming 工作原则上可以将其输出写入消息代理,但框架并没有真正使这个简单。似乎 Storm / Spark 不是以一种拓扑输出为另一拓扑输入的方式使用的。相比之下,在萨萨,这种使用模式是标准的。
到期
Spark 有一个活跃的用户和开发人员社区,最近发布了1.3.1版本。它有一个列表的公司,在其 Powered by 页面使用它。由于 Spark 包含 Spark Streaming,Spark SQL,MLlib,GraphX 和 Bagel,因此很难告诉列表中的哪些公司实际上是使用 Spark Streaming,而不仅仅是 Spark。
Samza 还很年轻,但刚刚发布了0.9.0版本。它有一个敏感的社区,正在积极发展。也就是说,它是建立在像 YARN 和 Kafka 这样的固体系统上。Samza 在 LinkedIn 和其他公司被大量使用。我们希望别人也会觉得有用。
更多建议: