评估好哪一种流处理架构模式最适合你的案例,是成功生产开发的先决条件。
ApacheHadoop生态系统已成为企业实时地处理和挖掘大数据的首选。Apache的Kafka,Flume,Spark,Storm,Samza等技术在不断地推进新的可能。人们很容易泛化大规模实时数据案例,但其实他们可以细分为几种架构模式,Apache系统里的不同组件适合于不同的案例。
这篇文章探讨四种主要的设计模式,案例来自于我们企业客户的数据中心的实例,并解释如何在Hadoop上实现这些架构模式。
流处理模式
四种流处理模式(经常为串联使用)为:
流采集:低延迟将数据输入到HDFS,ApacheHBase和ApacheSolr。
基于外部环境的准实时事件处理:对事件采取警报,标示,转化,过滤等动作。这些动作的触发可能取决于复杂的标准,例如异常监测模型。通常的使用案例——例如准实时的欺诈监测和推荐系统——需要达到毫秒以内的延迟。
准实时事件分割处理:类似于准实时事件处理,但通过将数据分割获得一些好处——例如将更多相关外部信息存入内存。这个模式也要求延迟在毫秒以内。
针对数据集成或机器学习的复杂拓扑结构:流处理的精髓。实时地通过复杂而灵活的操作从数据中获取答案和信息。这里,因为结果通常依赖于一段窗口内的计算,需要更多活跃的数据,于是重点从获得超低延迟转移到了功能性和准确性。
接下来,我们将介绍如何用可检测的,可被证明的和可维护的方式来实现这些设计模式。
?流采集传统上,Flume是最为推荐的流采集系统。它的数据源和数据池模块囊括了所有关于消费什么数据和将数据写到哪里的基础(关于如何配置和管理flume,参考UsingFlume,由O’Reilly出版的Cloudera工程师/Flume项目管理委员会成员HariShreedharan编写)。
在过去的一年中,因为playback和replication等特性,Kafka也变得非常受欢迎。由于Flume和Kafka有重叠的目标,他们的关系常常令人困惑。那么他们到底如何配合?答案是简单的:虽然Kafka的管道和Flume的通道类似,但由于Kafka所具备的上述特性,它相对来说是一个更好的管道。于是一个通行的方法就是用Flume作为源(source)和池(sink),而Kafka作为是他们中间的管道。
下图阐明Kafka如何作为Flume的上游数据源和下游目的地,或Flume的管道。
下图的设计是一个典型的案例。它具有大规模拓展性,经过实战检验的架构设计,由Cloudera管理者监控,容错,并且支持回放。
另外值得注意的一件事就是这个设计对于故障处理的完美支持。Flume数据池从Kafka消费者集群里读取数据。借助于ApacheZookeeper的帮助,Kafka消费者集群可以实时跟踪不同Topic分区的读取位置。如果一个Flume池发生故障,Kafka消费者可以迅速根据跟踪到的读取位置将把负载重新分发到其他的Flume池中。当故障池恢复功能之后,Kafak消费者池将再次进行重新分发。
基于外部环境的准实时事件处理
在介绍这个设计模式之前需要再重申一下,这个模式的适用案例通常是观察数据事件输入,然后立即进行数据转化或一些外部操作。决策的逻辑依赖于外部的数据档案或元数据。一个简单并且可拓展的实现方法是,在你的Kafka/Flume架构中添加源(Source)或池(Sink)Flume拦截器。只需简单配置,不难达到低毫秒级延迟。
Flume拦截器允许用户通过代码对事件或批量事件进行修改或采取相应的操作。用户代码可以与本地内存或外部Hbase交互,以获取决策需要的数据档案。根据网络状况、模式概要、设计和配置的不同,Hbase通常可以在4-25毫秒内提供给我们所需要的信息。你也可以将Hbase配置为即便在故障情况下,也永远不会停止或中断服务。
这一设计模式的实现除了拦截器应用的具体逻辑之外几乎不需要编程。Cloudera管理器提供直观的用户界面,可以部署整个逻辑,包括连结,配置,监测这一服务。
准实时基于外部环境的分割化事件处理
在下图所示的架构中(未分割方案),因为针对某一事件的外部上下文环境在Flume拦截器的本地内存中装不下,所以系统将需要频繁查询Hbase。
但是,如果你通过定义一个键值来分割数据,你将可以把数据流匹配到相关上下文的一个子集中。比如,你将数据分割成十部分,那么你只需要将十分之一的数据档案放入内存里。不可否认,HBase已经很快了,但本地内存更快。Kafka允许你自定义分割器来分割数据,大大降低处理延时。
另外值得注意的一件事是,在这个分割器模块中Flume并不是必须的;根本的方案其实只是一个Kafka消费者。所以,你可以只用一个YARN消费者或只有Mapper的MapReduce来完成这个过程。
?针对数据集成或机器学习的复杂拓扑
到此为止,我们探索了事件层面的操作。然而,有时你需要更复杂的操作,例如计数,求平均,或基于流数据的机器学习建模。在这种情况下,Spark流处理是最理想的的工具,因为:
和其他工具相比,Spark易于开发:Spark丰富简明的API让构建复杂拓扑变得更容易;
实时流处理和批处理的代码很类似:只需很少的修改,实时小量流处理的代码就可以用于大规模离线的批处理。不仅减少了代码量,也减少了测试和整合需要的时间;
只需了解一个技术引擎:训练员工了解一个分布式处理引擎的机制和构件是有成本的。使用spark并将其标准化会合并了解流处理和批处理的成本;
微批处理帮你更可靠地进行规模化:在批处理层面的应答可以实现更大规模的吞吐量,且无双发风险。微批处理同时也能高并发地修改HDFS或Hbase;
与Hadoop生态系统的集成:Spark与HDFS,Hbase和Kafka有很深的集成关系;
无丢失数据的风险:由于有了WAL和Kafka,Spark流处理避免了故障时丢失数据的风险;
易于排错和运行:在本地的IDE中你就可以对你的spark流处理代码进行排错和逐步检查。而且,代码和普通函数式程序代码类似,对Java或Scala程序员来说,无需花很多时间就能熟悉。(Python也支持);
流处理是天然状态化的:Spark流处理中,状态是“第一公民”。这意味着写基于状态的流处理应用并不难,且对节点的故障可恢复;
作为实际的标准,Spark现在正在得到整个生态系统的长期投入:在写作此文时,spark在30天内已有次左右的提交——和其它框架相比,例如Storm,只有15次的提交;
你可以使用机器学习的库:Spark的MLlib库越来越受欢迎,它的功能只会越来越强大;
如果需要,你可使用SQL结构化查询语言:通过SparkSQL,你可以为你的流处理应用添加SQL逻辑,从而简化代码。
结论
流处理以及它几种可能的设计模式有着相当强大的功能。但正如你在这篇文章中所了解到的,你如果知道哪一种设计模式更适合你的案例,就可以用最少量的代码完成你的目标。
译文作者:李若冰,硕士毕业于卡内基梅隆娱乐技术中心,本科就读于浙江大学计算机专业。现在微软Xbox从事后端开发,数据发掘和搜索服务方面的工作。原文作者:TedMalaska,TedMalaska是Cloudera解决方案架构师,Spark,Flume和Hbase的贡献者,O’Reilly书籍《Hadoop应用架构》的合作作者。