65.9K
CodeProject 正在变化。 阅读更多。
Home

使用SMACK进行数据处理:Spark、Mesos、Akka、Cassandra和Kafka

starIconstarIconstarIconstarIconstarIcon

5.00/5 (3投票s)

2017年1月25日

CPOL

11分钟阅读

viewsIcon

10811

本文介绍了SMACK(Spark、Mesos、Akka、Cassandra和Kafka)技术栈,并阐述了如何使用它来构建可伸缩的数据处理平台。

使用SMACK进行数据处理:Spark、Mesos、Akka、Cassandra和Kafka

本文介绍了SMACK(Spark、Mesos、Akka、Cassandra和Kafka)技术栈,并阐述了如何使用它来构建可伸缩的数据处理平台。尽管SMACK技术栈非常简洁,只包含几个组件,但可以在其中实现不同的系统设计,不仅包括纯粹的批处理或流处理,还包括更复杂的Lambda和Kappa架构。

什么是SMACK技术栈?

首先,我们来谈谈SMACK是什么。以下是其中包含的技术的快速概览:

Spark - 一个用于分布式大规模数据处理的快速通用引擎。

Mesos - 一个集群资源管理系统,提供分布式应用程序之间高效的资源隔离和共享。

Akka - 一个用于在JVM上构建高并发、分布式、弹性的消息驱动应用程序的工具包和运行时。

  • Cassandra - 一个分布式高可用数据库,旨在处理跨多个数据中心的大量数据。
  • Kafka - 一个高吞吐量、低延迟的分布式消息系统/提交日志,旨在处理实时数据流。

存储层:Cassandra

虽然不是按字母顺序排列,但我们首先从SMACK中的“C”开始。Cassandra以其高可用性和高吞吐量特性而闻名,能够处理大量的写入负载并能在集群节点故障后继续运行。根据CAP定理,Cassandra为操作提供可调的一致性/可用性。

最有趣的是,在数据处理方面,Cassandra具有线性可伸缩性(通过向集群添加更多节点即可处理增加的负载),并且它提供跨数据中心复制(XDCR)功能。实际上,XDCR不仅提供数据复制,还提供一系列用例,包括:

  • 处理特定于区域或更靠近客户的地理分布式数据中心。
  • 跨数据中心的数据迁移:故障恢复或将数据移动到新的数据中心。
  • 分离操作和分析工作负载。

然而,所有这些特性都有其代价,对于Cassandra来说,这个代价就是它的数据模型。这可以被认为是按分区键分布在集群节点上的嵌套排序映射,并且条目按聚类列排序/分组。示例如下:

要获取某个范围内的特定数据,必须指定完整键,除了列表中的最后一列,不允许使用范围子句。引入此限制是为了限制对不同范围的多次扫描,这可能会导致对磁盘的随机访问并降低性能。这意味着数据模型应根据读取查询进行仔细设计,以限制读取/扫描量,从而在支持新查询时降低灵活性。

但是,如果有一些表需要与另一个表进行某种方式的连接怎么办?考虑以下情况:计算所有活动的给定月份的每个活动的总视图。

使用给定模型,实现此目标的唯一方法是读取所有活动,读取所有事件,汇总属性(与匹配的活动ID)并将其分配给活动。实现此类应用程序可能非常具有挑战性,因为存储在Cassandra中的数据量可能非常庞大并超出内存容量。因此,此类数据应以分布式方式处理,而Spark非常适合此类用例。

处理层:Spark

Spark主要操作的抽象是RDD(弹性分布式数据集,一种分布式元素集合),其工作流程包括四个主要阶段:

  • RDD操作(转换和动作)形成DAG(有向无环图)。
  • DAG被分成任务阶段,然后提交给集群管理器。
  • 阶段组合不需要混洗/重新分区的任务。
  • 任务在worker上运行,结果返回给客户端。

以下是如何使用Spark和Cassandra解决上述问题:

与Cassandra的交互通过Spark-Cassandra连接器执行,这使得整个过程变得简单明了。还有一个更有趣的选项可以与NoSQL存储一起使用,那就是SparkSQL,它将SQL语句转换为一系列RDD操作。

只需几行代码,就可以实现简单的Lambda设计,当然这可以更复杂,但此示例仅展示了实现此目的的便捷性。

几乎是MapReduce:将处理靠近数据

Spark-Cassandra连接器是数据局部性感知的,它从集群中最近的节点读取数据,从而最大限度地减少通过网络传输的数据量。为了充分利用Spark-C*连接器的数据局部性感知能力,Spark worker应与Cassandra节点并置。

上图说明了Spark与Cassandra的并置。将操作性(或写入密集型)集群与分析集群分离是有意义的。原因如下:

  • 集群可以独立扩展。
  • 数据由Cassandra复制,无需额外工作。
  • 分析集群具有不同的读/写负载模式。
  • 分析集群可以包含额外的数据(例如,字典)和处理结果。
  • Spark资源的影响仅限于一个集群。

我们再来看一下Spark应用程序部署选项:

如上所示,集群资源管理器有三个主要选项:

  • Spark Standalone — Spark(作为主节点)和worker作为独立应用程序安装和执行(这显然会引入一些开销,并且每个worker只支持静态资源分配)。
  • YARN — 如果您已经有Hadoop,则运行得非常好。
  • Mesos — 从一开始,Mesos就被设计用于集群资源的动态分配,不仅用于运行Hadoop应用程序,还用于处理异构工作负载。

Mesos架构

SMACK中的“M”代表Mesos架构。Mesos集群由负责资源提供和调度的主节点以及负责实际繁重任务执行的从节点组成。

在具有多个主节点的高可用模式下,ZooKeeper用于领导者选举和服务发现。在Mesos上执行的应用程序称为框架,并利用API来处理资源提供并将任务提交给Mesos。通常,任务执行过程包括以下步骤:

  1. 从节点向主节点提供可用资源。
  2. 主节点向框架发送资源提供。
  3. 调度程序回复任务以及每个任务所需的资源。
  4. 主节点将任务发送给从节点。

将Spark、Mesos和Cassandra结合起来

如前所述,Spark worker应与Cassandra节点并置,以强制执行数据局部性感知,从而降低网络流量和Cassandra集群负载。以下是使用Mesos实现此目的的一种可能的部署场景:

  • Mesos主节点和ZooKeepers并置。
  • Mesos从节点和Cassandra节点并置,以强制执行Spark更好的数据局部性。
  • Spark二进制文件部署到所有worker节点,并配置spark-env.sh以指定正确的主端点和执行器JAR位置。
  • Spark执行器JAR上传到S3/HDFS。

通过提供的设置,可以从安装了Spark二进制文件并上传了包含实际作业逻辑的assembly JAR的任何worker节点通过简单的spark-submit调用将Spark作业提交到集群。

存在运行Dockerized Spark的选项,这样就不需要将二进制文件分发到每个集群节点。

计划和长时间运行的任务执行

每个数据处理系统迟早都会面临运行两类作业的需求:计划/周期性作业,如周期性批处理聚合,以及长时间运行的作业,这是流处理的情况。这两种类型的主要要求是容错性——即使集群节点发生故障,作业也必须继续运行。Mesos生态系统提供了两个出色的框架,支持这两种类型的作业。Marathon是一个用于长时间运行任务的容错执行框架,支持带有ZooKeeper的高可用模式,能够运行Docker并具有出色的REST API。以下是使用shell命令运行spark-submit进行简单作业配置的示例:

Chronos具有与Marathon相同的特性,但旨在运行计划作业,通常它是一个分布式高可用 cron,支持作业图。以下是作为简单bash脚本实现的S3压缩作业配置示例:

目前已有或正在积极开发许多框架(例如Hadoop、Cassandra、Kafka、Myriad、Storm和Samza),旨在将广泛使用的系统与Mesos资源管理功能集成。

摄取数据

到目前为止,我们已经设计了存储层,设置了资源管理,并配置了作业。唯一尚未就位的是要处理的数据:

假设传入数据将以高速率到达,接收数据的端点应满足以下要求:

  • 提供高吞吐量/低延迟
  • 具有弹性
  • 易于扩展
  • 支持背压

再想想,背压并非必需,但将其作为处理负载峰值的选项会很好。Akka完美符合这些要求,并且基本上就是为了提供这套功能而设计的。以下是您可以从Akka中获得的好处快速概览:

  • JVM的Actor模型实现
  • 基于消息和异步
  • 强制执行非共享可变状态
  • 易于从一个进程扩展到机器集群
  • Actor通过父级监督形成层次结构
  • 不仅是并发框架:akka-http、akka-streams和akka-persistence

这是一个简化的示例,展示了三个Actor如何处理JSON HttpRequest,将其解析为领域模型case类,并将其保存到Cassandra:

看起来只需要几行代码就能让一切正常工作,但是在使用Akka将原始数据(事件)写入Cassandra时,可能会出现以下问题:

  • Cassandra仍然设计用于快速服务而非批处理,因此需要对传入数据进行预聚合
  • 聚合/汇总的计算时间会随着数据量的增加而增长
  • 由于无状态设计模型,Actor不适合执行聚合
  • 微批处理可以部分解决问题
  • 仍然需要某种可靠的原始数据缓冲区

Kafka作为传入数据的缓冲区

为了保留具有一定保留期的传入数据并对其进行进一步的预聚合/处理,可以使用某种分布式提交日志。在这种情况下,消费者将批量读取数据,处理数据并以预聚合的形式将其存储到Cassandra中。

以下是使用akka-http通过HTTP将JSON数据发布到Kafka的示例:

消费数据:Spark Streaming

虽然Akka仍然可以用于从Kafka消费流数据,但您的生态系统中拥有Spark可以将Spark Streaming作为解决以下问题的选项:

  • 它支持各种数据源
  • 它提供至少一次语义
  • 通过Kafka Direct和幂等存储提供精确一次语义

以下是使用Spark Streaming从Kinesis消费事件流的示例:

故障设计:备份和修补

这通常是任何系统中最枯燥的部分,但当数据中心不可用或在数据中心故障时进行分析时,以一切可能的方式保护数据免受损失确实非常重要。

那为什么不将数据存储在Kafka/Kinesis中呢?

在撰写本文时,Kinesis是唯一一种在所有处理结果丢失时无需备份即可保留数据的解决方案。虽然Kafka支持较长的保留期,但应考虑硬件拥有成本,因为例如S3存储比运行多个Kafka实例便宜得多,并且S3 SLA非常好。

除了备份之外,还应预先设计和测试恢复/修补策略,以便可以快速修复任何数据问题。程序员在聚合作业中的错误或重复数据删除可能会破坏计算结果的准确性。因此,能够修复此类错误非常重要。使所有这些操作更容易的一件事是强制数据模型中的幂等性,以便多次重复相同的操作产生相同的结果(例如,SQL更新是幂等操作,而计数器增量则不是)。

以下是一个Spark作业的示例,该作业读取S3备份并将其加载到Cassandra中:

SMACK:全貌

到此,我们对SMACK的广泛描述就结束了。为了让您更好地可视化使用SMACK构建的数据平台设计,这里是架构的可视化描述:

在上面的文章中,我们讨论了使用SMACK的一些基本功能。最后,以下是其主要优点的快速概览:

  • 用于各种数据处理场景的简洁工具箱
  • 经过实战检验且广泛使用的软件,拥有庞大的支持社区
  • 轻松扩展和复制数据,同时保持低延迟
  • 异构负载的统一集群管理
  • 适用于任何类型应用程序的单一平台
  • 各种架构设计(批处理、流处理、Lambda或Kappa)的实现平台
  • 极快的上市时间(例如,用于MVP验证)

感谢您的阅读。如果有人有使用SMACK开发应用程序的经验,请留下评论。

© . All rights reserved.