/ 中存储网

从Storm和Spark学习流式实时分布式计算的设计

2014-08-04 11:28:00 来源:中存储网

流式实时分布式计算系统在互联网公司占有举足轻重的地位,尤其在在线和近线的海量数据处理上。而处理这些海量数据的,就是实时流式计算系统。Spark是实时计算的系统,支持流式计算,批处理和实时查询。除了Spark,流式计算系统最有名的就是Twitter的Storm和Yahoo的S4。作者参考Storm和Spark探讨流式计算系统的设计要点。本文来自CSDN博客。


免费订阅“CSDN大数据”微信公众号,实时了解最新的大数据进展!

CSDN大数据,专注大数据资讯、技术和经验的分享和讨论,提供Hadoop、Spark、Imapala、Storm、HBase、MongoDB、Solr、机器学习、智能算法等相关大数据观点,大数据技术,大数据平台,大数据实践,大数据产业资讯等服务。


以下为原文:

背景

最近我在做流式实时分布式计算系统的架构设计,而正好又要参见CSDN博文大赛的决赛。本来想就写Spark源码分析的文章吧。但是又想毕竟是决赛,要拿出一些自己的干货出来,仅仅是源码分析貌似分量不够。因此,我将最近一直在做的系统架构的思路整理出来,形成此文。为什么要参考Storm和Spark,因为没有参照效果可能不会太好,尤其是对于Storm和Spark由了解的同学来说,可能通过对比,更能体会到每个具体实现背后的意义。

本文对流式系统出现的背景,特点,数据HA,服务HA,节点间和计算逻辑间的消息传递,存储模型,计算模型,与生产环境融合都有涉及。希望对大家的工作和学习有所帮助。

正文开始:

流式实时分布式计算系统在互联网公司占有举足轻重的地位,尤其在在线和近线的海量数据处理上。在线系统负责处理在线请求,因此低延时高可靠是核心指标。在线系统是互联网公司的核心,系统的好坏直接影响了流量,而流量对互联网公司来说意味着一切。在线系统使用的数据是来自于后台的计算系统产生的。

对于在线(区别于响应互联网用户请求的在线系统,这个在线系统主要是内部使用的,也就是说并不直接服务于互联网用户)/近线系统来说,处理的是线上产生的数据,比如在线系统产生的日志,记录用户行为的数据库等,因此近线系统也需要低延时高可靠的处理海量数据。对于那些时效性很强的数据,比如新闻热点,电商的促销,微博热词等都需要在很短的时间内完成数据处理以供在线系统使用。

而处理这些海量数据的,就是实时流式计算系统。Spark是实时计算的系统,支持流式计算,批处理和实时查询。它使用一个通用的stack解决了很多问题,毕竟任何公司都想要Unified的平台去处理遇到的问题,可以减少开发和维护的人力成本和部署平台的物力成本。除了Spark,流式计算系统最有名的就是Twitter的Storm和Yahoo的S4(其实Spark的流式计算还是要弱于Storm的,个人认为互联网公司对于Storm的部署还是多于Spark的)。

本文主要探讨流式计算系统的设计要点,并且通过对Spark和Storm的实现来给出实例。通过对于系统设计要点的梳理,也可以帮助我们更好的学习这些系统的实现。最后,看一下国内互联网公司对于这些流式系统的应用(仅限于公开发表的内容)。

流式计算的背景和特点

现在很多公司每天都会产生数以TB级的大数据,如何对这些数据进行挖掘,分析成了很重要的课题。比如:

  1. 电子商务:需要处理并且挖掘用户行为产生的数据,产生推荐,从而带来更多的流量和收益。最理想的推荐就是根据兴趣推荐给用户本来不需要的东西!而每天处理海量的用户数据,需要一个低延时高可靠的实时流式分布式计算系统。
  2. 新闻聚合:新闻时效性非常重要,如果在一个重大事情发生后能够实时的推荐给用户,那么肯定能增大用户粘性,带来可观的流量。
  3. 社交网站:大家每天都会去社交网站是为了看看现在发生了什么,周围人在做什么。流式计算可以把用户关注的热点聚合,实时反馈给用户,从而达到一个圈子的聚合效果。
  4. 交通监管部门:每个城市的交通监管部门每天都要产生海量的视频数据,这些视频数据也是以流的形式源源不断的输系统中。实时流式计算系统需要以最快的速度来处理这些数据。
  5. 数据挖掘和机器学习:它们实际上是互联网公司内部使用的系统,主要为线上服务提供数据支撑。它们可以说是互联网公司的最核心的平台之一。系统的效率是挖掘的关键,理想条件下就是每天产生的海量数据都能得到有效处理,对于原来的数据进行全量更新。
  6. 大型集群的监控:自动化运维很重要,集群监控的实时预警机制也非常重要,而流式系统对于日志的实时处理,往往是监控系统的关键。
  7. 等等。

流式实时分布式计算系统就是要解决上述问题的。这些系统的共同特征是什么?

  1. 非常方便的运行用户编写的计算逻辑:就如Hadoop定义了Map和Reduce的原语一样,这些系统也需要让用户关注与数据处理的具体逻辑上,他们不应该也不需要去了解这些usder defined codes是如何在分布式系统上运转起来的。因为他们仅仅关注与数据处理的逻辑,因此可以极大的提高效率。而且应该尽量不要限制编程语言,毕竟不同的公司甚至同一公司的不同部门使用的语言可能是千差万别的。支持多语言无疑可以抢占更多的用户。
  2. Scale-out的设计:分布式系统天生就是scale-out的。
  3. 无数据丢失:系统需要保证无数据丢失,这也是系统高可用性的保证。系统为了无数据丢失,需要在数据处理失败的时候选择另外的执行路径进行replay(系统不是简单的重新提交运算,而是重新执行调度,否则按照来源的call stack有可能使得系统永远都在相同的地方出同样的错误)。
  4. 容错透明:用户不会也不需要关心容错。系统会自动处理容错,调度并且管理资源,而这些行为对于运行于其上的应用来说都是透明的。
  5. 数据持久化:为了保证高可用性和无数据丢失,数据持久化是无法躲避的问题。的确,数据持久化可能在低延时的系统中比较影响性能,但是这无法避免。当然了,如果考虑到出错情况比较少,在出错的时候我们能够忍受数据可以从头replay,那么中间的运算可以不进行持久化。注意,这只有在持久化的成本要比计算的replay高的情况下有效。一般来说,计算的结果需要replica,当然了,可以使用将数据replica到其他的节点的内存中去(这又会占用集群的网络带宽)。
  6. 超时设置:超时之所以在在这里被提出来,因为超时时间的大小设置需要重视,如果太短可以会误杀正常运行的计算,如果太长则不能快速的检测错误。还有就是对于错误的快速发现可以这类系统的一个设计要点,毕竟,超时了才发现错误很多时候在时效性上是不可接受的。

原语设计

Hadoop定义了Map和Reduce,使得应用者只需要实现MR就可以实现数据处理。而流式系统的特点,允许它们可以进行更加具体一些的原语设计。流式的数据的特点就是数据时源源不断进入系统的,而这些数据的处理一般都需要几个阶段。拿普通的日志处理来说,我们可能仅仅关注Error的日志,那么系统的第一个计算逻辑就是进行filer。接下来可能需要对这个日志进行分段,分段后可能交给不同的规则处理器进行处理。因此,数据处理一般是分阶段的,可以说是一个有向无环图,或者说是一个拓扑。实际上,Spark抽象出的运算逻辑就是由RDD(Resilient Distributed Dataset)构成DAG(Directed Acyclic Graph),而Storm则有Spout和Blot构成Topology(拓扑)。

Spark的设计

Spark Streaming是将流式计算分解成一系列短小的批处理作业。这里的批处理引擎是Spark,也就是把Spark Streaming的输入数据按照batch size(如1秒)分成一段一段的数据,每一段数据都转换成Spark中的RDD,然后将Spark Streaming中对DStream的Transformation操作变为针对Spark中对RDD的Transformation操作,将RDD经过操作变成中间结果保存在内存中。整个流式计算根据业务的需求可以对中间的结果进行叠加,或者存储到外部设备。下图显示了Spark Streaming的整个流程。


WordCount的例子:


这个例子使用Scala写的,一个简单优雅的函数式编程语言,同时也是基于JVM的后Java类语言。

Storm的设计

Storm将计算逻辑成为Topology,其中Spout是Topology的数据源,这个数据源可能是文件系统的某个日志,也可能是MessageQueue的某个消息队列,也有可能是数据库的某个表等等;Bolt负责数据的护理。Bolt有可能由另外两个Bolt的join而来。

而Storm最核心的抽象Streaming就是连接Spout,Bolt以及Bolt与Bolt之间的数据流。而数据流的组成单位就是Tuple(元组),这个Tuple可能由多个Fields构成,每个Field的含义都在Bolt的定义的时候制定。也就是说,对于一个Bolt来说,Tuple的格式是定义好的。


原语设计的要点

流式系统的原语设计,要关注一下几点:

  1. 如何定义计算拓扑:要方便算法开发者开发算法与策略。最好的实现是定义一个算法与框架的交互方式,定义好算法的输入结构和算法的输出结构。然后拓扑能够组合不同的算法来为用户提供一个统一的服务。计算平台最大的意义在于算法开发者不需要了解程序的运行,并发的处理,高可用性的实现,只需要提供算法与计算逻辑即可以快速可靠的处理海量的数据。
  2. 拓扑的加载与启动:对于每个节点来说,启动时需要加载拓扑,节点需要其他的信息,比如上游的数据来源与下游的数据输出。当然了下游的数据输出的拓扑信息可以存储到Tuple中,对于数据需要放到那里去拓扑本身是无状态的。这就取决于具体的设计了。
  3. 拓扑的在线更新:对于每个算法逻辑来说,更新是不可避免的,如何在不停止服务的情况下进行更新是必要的。由于实现了架构与算法的剥离,因此算法可以以一个单独的个体进行更新。可以操作如下:Master将算法实体保存到一个Worker可见的地方,比如HDFS或者是NFS或者ZK,然后通过心跳发送命令到拓扑,拓扑会暂时停止处理数据而加载新的算法实体,加载之后重新开始处理数据。数据一般都会放到buffer中,这个buffer可能是一个queue。但是从外界看来,拓扑实际上是一直处于服务状态的。
  4. 数据如何流动:流式系统最重要的抽象就是Streaming了。那么Steaming如何流动?实际上涉及到消息的传递和分发,数据如何从一个节点传递到另外一个节点,这是拓扑定义的,具体实现可以参照第三小节。
  5. 计算的终点及结果处理:流式计算的特点就是计算一直在进行,流是源源不断的流入到系统中的。但是对于每个数据单位来说它的处理结果是确定的,这个结果一般是需要返回调用者或者需要持久化的。比如处理一个时间段的交通违章,那么输入的数据是一段时间的视频监控,输出这是违章的信息,比如车牌,还有违章时刻的抓拍的图片。这个数据要么返回调用者,由调用者负责数据的处理,包括持久化等。或者是拓扑最后的节点将这些信息进行持久化。系统需要对这些常见的case进行指导性的说明,需要在Programmer Guide的sample中给出使用例子。