20
30 第四章 流数据管理系统 4.1 概述 早在本世纪初,学术界针对数据流的处理已经开展了相关的研究工作,推出了早期的数 据流管理系统 AuroraBorealis STREAM 等。如今,为满足处理流式大数据的实时性、 负载均衡和容错处理等需求,学术界和工业界相继推出了 StormS4Puma Samza 等流 数据管理系统。 针对流数据的实时处理流程往往包含三个阶段:数据实时采集阶段、数据实时计算阶段 和数据持久化存储阶段。其中,数据采集阶段包含多种数据收集方式,包括使用消息队列 RabbitMQ 等),或直接通过网络 Socket 传输数据,或利用前端业务系统专有的数据采集 API 等等。 本节首先针对数据采集较为通用的方案—消息队列进行系统介绍,然后将重点对 StormS4Puma Samza 系统进行对比分析和详细说明。 4.2 消息队列 通信领域中的电话记录数据流、Web 上的用户点击数据流、网络监测中的数据包流、 各类传感器网络中的监测数据流、金融领域的证券数据流、卫星传回的图像数据流以及零售 业务中的交易数据流等形成了一种与传统数据库中静态数据不同的数据形态。 在传统静态数据集的处理过程中,往往借助一些数据导入工具把待处理的数据集批量导 入到数据处理系统中,或以数据库文件的形式,或导入到分布式文件系统中(如:HDFS等。在流数据的产生和采集过程中,数据源的实时性和持续性给数据采集工作带来了很大的 挑战。首先在功能上,要保证可以完整地收集到所有数据,为实时应用提供实时数据;其次 在响应时间上,需要保证实时性、低延迟;另外,还要求系统配置简单、部署容易,稳定可 靠等。目前较为流行的产品包括:Facebook Scribe[1]LinkedIn Kafka[2]Cloudera Flume[3]Hadoop Chukwa[4]等,均可以满足每秒数百 MB 的日志数据采集和传输需求。 Apache Flume Cloudera 2009 7 月发布的一个分布式的、可靠的、高可用的海量 日志聚合系统,支持在系统中定制各类数据发送方,用于收集数据,把数据集中到一个中心 化的存储中。Scribe Facebook 开源的日志收集系统,在 Facebook 内部已经得到大量的应 用。它能够从各种日志源上收集日志,存储到一个中央存储系统 (可以是 NFS,分布式文 件系统等)上,以便于进行集中统计分析处理。它为日志的“分布式收集,统一处理”提供 了一个可扩展的,高容错的方案。Sqoop[5]Apache 下用于 RDBMS HDFS 互相导数据的 工具。 Chukwa Apache 的开源项目,由于其属于 Hadoop 系列产品,因而使用了很多 Hadoop 的组件(用 HDFS 存储,用 MapReduce 处理数据),它提供了很多模块以支持 Hadoop 集群 日志分析。本节将详细介绍 RabbitMQKafka SpringXD4.2.1 RabbitMQ RabbitMQ[6]是流行的开源消息队列系统,用 erlang 语言开发,是 AMQP(高级消息队 列协议)的标准实现。最初起源于金融系统,用于在分布式系统中存储转发消息,在易用性、 扩展性、高可用性等方面表现不俗。消息中间件主要用于组件之间的解耦,消息的发送者无 需知道消息使用者的存在,反之亦然。 RabbitMQ 1.0.0-alpha 版本于 2007 年由 Rabbit 科技有限公司发布并提供商业支持。起初, Rabbit 科技是 LSHIFT CohesiveFT 2007 年成立的合资企业,该公司于 2010 4 月被 VMware 公司旗下的 SpringSource 部门收购,并在 2013 5 月被并入 Pivotal

第四章 流数据管理系统 - idke.ruc.edu.cnidke.ruc.edu.cn/resources/Big Data Reports/Chapter4.pdf · 支持多种通信协议:AMQP, STOMP, MQTT, HTTP。 支持多种语言编写客户端程序:Java,

Embed Size (px)

Citation preview

30

第四章 流数据管理系统

4.1 概述

早在本世纪初,学术界针对数据流的处理已经开展了相关的研究工作,推出了早期的数

据流管理系统 Aurora,Borealis 和 STREAM 等。如今,为满足处理流式大数据的实时性、

负载均衡和容错处理等需求,学术界和工业界相继推出了 Storm,S4,Puma 和 Samza 等流

数据管理系统。

针对流数据的实时处理流程往往包含三个阶段:数据实时采集阶段、数据实时计算阶段

和数据持久化存储阶段。其中,数据采集阶段包含多种数据收集方式,包括使用消息队列

(RabbitMQ 等),或直接通过网络 Socket 传输数据,或利用前端业务系统专有的数据采集

API 等等。

本节首先针对数据采集较为通用的方案—消息队列进行系统介绍,然后将重点对 Storm,

S4,Puma 和 Samza 系统进行对比分析和详细说明。

4.2 消息队列

通信领域中的电话记录数据流、Web 上的用户点击数据流、网络监测中的数据包流、

各类传感器网络中的监测数据流、金融领域的证券数据流、卫星传回的图像数据流以及零售

业务中的交易数据流等形成了一种与传统数据库中静态数据不同的数据形态。

在传统静态数据集的处理过程中,往往借助一些数据导入工具把待处理的数据集批量导

入到数据处理系统中,或以数据库文件的形式,或导入到分布式文件系统中(如:HDFS)

等。在流数据的产生和采集过程中,数据源的实时性和持续性给数据采集工作带来了很大的

挑战。首先在功能上,要保证可以完整地收集到所有数据,为实时应用提供实时数据;其次

在响应时间上,需要保证实时性、低延迟;另外,还要求系统配置简单、部署容易,稳定可

靠等。目前较为流行的产品包括:Facebook 的 Scribe[1]、LinkedIn 的 Kafka[2]、Cloudera 的

Flume[3],Hadoop 的 Chukwa[4]等,均可以满足每秒数百 MB 的日志数据采集和传输需求。

Apache Flume 是 Cloudera 于 2009 年 7 月发布的一个分布式的、可靠的、高可用的海量

日志聚合系统,支持在系统中定制各类数据发送方,用于收集数据,把数据集中到一个中心

化的存储中。Scribe 是 Facebook 开源的日志收集系统,在 Facebook 内部已经得到大量的应

用。它能够从各种日志源上收集日志,存储到一个中央存储系统 (可以是 NFS,分布式文

件系统等)上,以便于进行集中统计分析处理。它为日志的“分布式收集,统一处理”提供

了一个可扩展的,高容错的方案。Sqoop[5]是 Apache 下用于 RDBMS 和 HDFS 互相导数据的

工具。Chukwa 是 Apache 的开源项目,由于其属于 Hadoop 系列产品,因而使用了很多 Hadoop

的组件(用 HDFS 存储,用 MapReduce 处理数据),它提供了很多模块以支持 Hadoop 集群

日志分析。本节将详细介绍 RabbitMQ、Kafka 和 SpringXD。

4.2.1 RabbitMQ

RabbitMQ[6]是流行的开源消息队列系统,用 erlang 语言开发,是 AMQP(高级消息队

列协议)的标准实现。最初起源于金融系统,用于在分布式系统中存储转发消息,在易用性、

扩展性、高可用性等方面表现不俗。消息中间件主要用于组件之间的解耦,消息的发送者无

需知道消息使用者的存在,反之亦然。

RabbitMQ 1.0.0-alpha 版本于 2007 年由 Rabbit 科技有限公司发布并提供商业支持。起初,

Rabbit 科技是 LSHIFT 和 CohesiveFT 在 2007 年成立的合资企业,该公司于 2010 年 4 月被

VMware 公司旗下的 SpringSource 部门收购,并在 2013 年 5 月被并入 Pivotal。

31

图 4.1 RabbitMQ 系统架构图

RabbitMQ 的系统架构如图 4.1 所示,主要包括四个核心组件:

生产者(Producer):负责产生、发送消息的角色。

消费者(Consumer):负责接收、处理消息的角色。

队列(Queue)

队列是 RabbitMQ 内部对象,用于存储消息。队列的属性可设置为:1)持久化(durable):

若启用,队列将会在服务器重启前都有效;2)自动删除(auto-delete):若启用,队列将会

在所有的消费者停止使用后自动删除;3)排他(exclusive):若启用,队列只能被声明它的

消费者使用。

交换机(Exchange)

消息交换机,它在得到消息后会依据规则把消息发送到一个或多个队列当中。常用的交

换机的类型包括:1)fanout:采取广播模式,把消息转发给所有绑定的队列上,如图 4.2(a)

所示;2)direct:“先匹配,再投递”,即在绑定时设定一个 routing_key,消息的 routing_key

匹配时,才会被交换器投递到绑定的队列中去,如图 4.2(b)所示;3)topic:类似于 direct

类型,只是匹配上支持了“模式”匹配,如图 4.2(c)所示。

图 4.2(a) exchange 类型:fanout

图 4.2(b) exchange 类型:direct 图 4.2(c) exchange 类型:topic

RabbitMQ 的特性包括:

支持多种通信协议:AMQP, STOMP, MQTT, HTTP。

支持多种语言编写客户端程序:Java, Ruby, Python, .Net, Php, Perl, C/C++, Erlang, Node.js,

Cobol。

可靠性:消息持久化、消息确认机制等。

灵活的路由模型。

高可用性:镜像队列等。

作为一个功能强大的消息中间件,选择 RabbitMQ 的公司包括:淘宝、NASA、BBC、AT&T、

OpenStack、Mozilla 等等。

32

4.2.2 Kafka

Apache Kafka[2]是一个分布式发布-订阅消息系统,由 LinkedIn 公司于 2010 年 12 月发布,

它主要用于日志数据的处理。这里日志数据不仅包括系统运行过程中产生的各种服务日志,

也包括网页浏览、点击行为等用户行为事件。Kafka 采用 Scala 语言编写,使用了多种效率优

化机制,整体架构(push/pull)比较新颖,更适合异构集群。

Kafka 的系统架构如图 4.3 所示,核心组件包括:

生产者(Producer):指能够发布消息的任何对象,使用标准的推送(push)模型,将

消息推送到消息中介,这些消息都会有一个标签表示其所属的话题。

消费者(Consumer):可以订阅一个或多个话题(topic)。消费者使用拉取(pull)模型,

主动从代理中拉取消息,进而消费消息。

代理(Broker):保存消息的一组服务器,或称为 Kafka 集群。Kafka 支持在服务器集群

上进行消息分片(partition)。

Zookeeper:借助 Zookeeper 的协调机制保证负载均衡。

图 4.3 Kafka 系统架构图

Kafka 的设计目标包括:

高吞吐率:即使在普通的节点上每秒钟也能处理成百上千的消息。

消息持久化:数据在磁盘上存取代价为 O(1)。

显示分布式:所有的生产者、消费者、代理都有多个,均为分布式的。

支持数据并行加载到 Hadoop 中。

Kafka 使用的是 push+pull 的模型,生产者向代理推送(push)消息,消费者从代理中拉

取(pull)消息。不同于 Kafka,Scribe、Flume 等系统在消费者端采用的是推送模型。消息

推送的优势是,消息的实时性高,一旦消息中介接收到消息,可以马上推送给消费者。并且

方便维护消息的消费状态。但是缺点也较为明显,基于推送的方式不能得知消费者的状态,

如果碰到消费者比发送者慢的情况,很容易造成消费者的过载,最终崩溃。使用拉取模型,

消费者可以根据自己的状态选择何时拉取消息,以及拉取的消息数量,不会造成消费者的拥

堵。并且为了提升吞吐量,可以一次批量拉取多条消息。

LinkedIn 针对生产者、消费者的吞吐率,对 Kafka、RabbitMQ 和 ActiveMQ(Apache 的

项目)进行了对比测试。该测试利用 2 台机器作为实验平台,一台配置为代理,另一台配置

为生产者和消费者。生产者共发送 1000 万条消息,每条消息 200 字节。消费者将消息刷入

持久化库。生产者和消费者的测试结果分别如图 4.4(a)和图 4.4(b)所示。

33

4.4(a) 生产者吞吐率 4.4(b) 消费者吞吐率

4.2.3 Spring XD

Spring XD[7](eXtreme Data)是 Pivotal 的大数据产品。其第一个里程碑版本发布于 2013

年,GA 版本发布于 2014 年 7 月。Spring XD 是一个统一的、分布式、可扩展的系统,可用

于数据摄取,实时分析,批量处理和数据导出。Spring XD 利用了大量现存的 Spring 项目,

它的目标是为了简化大数据应用的开发。

4.5 Spring XD 系统架构图

Spring XD 的系统架构如图 4.5 所示。Spring XD 中的关键组件是管理服务器(Admin)和

容器服务器(Container)。通过 DSL,用户可以把所需处理任务的描述通过 HTTP 提交给管理

服务器。管理服务器会把处理的任务切分成彼此独立的模块(module)定义,并把每个模

块分配给容器实例。每个容器都会监听分配给它的模块定义,然后部署模块,创建 Spring

应用程序上下文来运行它。模块之间通过使用配置好的消息中间件传递消息来共享数据。传

输层是可插拔的,并且支持其他两种 Pivotal 项目——Redis 和 RabbitMQ。

在 Spring XD 中,每个模块(module)都是一个执行单元,作为 Spring 应用程序上下文

实现。一共有四种类型的模块:

Source:负责从外部数据源获取数据。Spring XD 内嵌了多种 Source 模块,包括:HTTP、

Tail、File、Mail、Twitter Search、Twitter Stream、TCP、Time、RabbitMQ、Gemfire Source

等等。

Sink:把数据输出到外部存储中。Spring XD 中内嵌的 Sink 模块包括:Log、File Sink、HDFS、

JDBC、TCP Sink、Mongo、Mail、RabbitMQ、GemFire Server 等等。

Processor:完成某种业务逻辑。在 Source和 Sink模块之间可以添加一个或多个Processor,

从而实现在数据摄取的过程中进行实时分析。Spring XD 中内嵌的 Processor 模块包括:

Fileter、Transform、Splitter、Aggregator 等等。

34

Job:实现工作流的调度。内嵌的 Job 模块包括:HDFSJDBC、JDBCHDFS、FileJDBC、FtpHDFS

等等。

SpringXD 提供了 DSL,一种描述性的语言来定义任务。下述语句创建一个名为“ticktock”

的流,流的定义为:Source 模块为 time,即每秒发送一条消息,消息内容即为当前时间;

Sink 模块为 log,即打印日志信息。deploy 选项表示流一旦创建成功,就开始部署运行。

xd:> stream create --name ticktock --definition “time | log” –deploy

SpringXD 中提供了 web UI。通过该用户接口,用户可以查看系统中有哪些容器服务器,

每个容器上部署了哪些模块,以及系统中创建的流,流的定义,还可以对流进行简单的管理。

图 4.6 Spring XD web UI

4.2.4 系统对比总结

表 4.1 对比总结了较为流行的一些消息队列系统:

表 4.1 消息队列系统对比分析

4.3 S4 系统介绍

S4[8],全称为 Simple Scalable Streaming System,是一种通用型的、分布式的、低延

迟的、可扩展的、可插拔的分布式流处理引擎。它最初是由 Yahoo!开发的,用来解决它

35

的一个现实问题:搜索广告的展现问题。搜索广告是当前各大搜索引擎的主要收入来源。用

户发出查询请求,搜索引擎在返回正常结果的同时也会返回相关广告,而广告是按照点击量

来计费。为了在最好的位置,放置最相关(即用户最有可能点击)的广告,各大搜索引擎使

用了大量的数据挖掘和机器学习算法来进行相关性计算,以便满足用户需求,并提高收入。

其中很重要的一点就是要不断分析用户的点击反馈,以便捕获用户的行为。后来,Yahoo!

将 S4 捐献给 Apache,进入 Apache incubator 进行项目孵化。

随着大量实时应用的发展,许多应用,如实时搜索、实时交易系统、实时欺骗分析、实

时监控、社交网络等,都需要一个高度可扩展的流式计算解决方案。不同于原来的流式计算

系统,S4 主要解决的是高数据率和大数据量下的流式处理。

4.3.1 整体介绍

图 4.7 展示了 S4 系统的整体架构。在 S4 中所有事件流均由 client 触发,经由 Adapter

到达 S4 集群进行分步式计算处理。关键的数据事件被分类路由到 S4 的各个处理单元

(Processing Elements,PEs),然后处理单元消费这些事件,做如下的部分或者全部事

情:

a.发出一个或多个可能被其他 PE 处理的事件;

b.发布结果。

图 4.7 S4 系统整体架构

S4 中,数据流(stream)是由一系列事件(event)构成的序列流。每个事件(event)

是一个(K,A)形式的元素,并通过 EventType 来表示其类型。其中,K、A 分别表示事件

的键(key)和属性(attribute),并均为 tuple-valued 类型的值,即“key=value”形式的

元组值。图 4.8 给出了一个事件的例子。图中,“KV”行指出事件的类型,“Key”行展示

了事件的键值,而“Val”这一行则给出事件的属性值。

图 4.8 事件(event)示例

36

处理单元(PEs)是 S4 中最基本的计算单元。一个 PE 通过下面四个组件来唯一标识:

功能(functionality):由实现该 PE 的 Java 类和相关配置来定义;

事件类型(types of events):该 PE 所消费或处理的事件类型;

属性 key(keyed attribute):该 PE 所消费的带 key 的属性,即该 PE 所关心的属性

key 的类型;属性值(value of keyed attribute):这些带 key 的属性所对应的属性值。

每个 PE 只消费事件类型、属性 key、属性值都匹配的事件。同时,它可能会产生输出

事件。当一个事件到达时,如果有匹配的 PE,则交由该 PE 处理;如果没有,则会创建一

个新的 PE。

图 4.9 展示了 S4 的一个简单的逻辑流图,主要包含 PE、流、事件这三个基本要素。

一个 PE 接收到匹配的事件后进行处理,然后输入事件到下一个 PE 或者直接输出结果。其

中,PE 和 PE 之间是靠有向的流来连接,而流中实际的消息个体是由事件来构成。

图 4.9 S4 逻辑流图

PE 主要分为两种类型:

(1)一种是无键的 PE(keyless PE),它没有定义属性 key 和属性值,能够消费指

定 EventType 的所有事件,通常这些事件是原始数据。这种 PE 一般在一个 S4 集群的输入

层使用,在这里,原始事件会被赋予一个 key 以便于分发给后面的 PE 处理。图 3 中,最左

端的两个 PE 就是无键的 PE。

(2)另一种是 PE 原型(PE prototype),它包含其身份标识的前 3 个元素(功能、

事件类型、属性 key),而属性值是未赋值的。这种 PE 在系统初始化时进行配置。对于任

意值 V,它能够克隆自己来创建相同类型、相同配置、以 V 为属性值的全限定的 PE 实例(PE

instance)。

处理节点(PN)是 PE 的逻辑主机,对应着集群中的一个逻辑节点,主要负责监听和

分发事件。当事件到达时,PN 将调用适合的 PE 处理事件;如果 PE 有输出,PN 还需和通

讯层(Communication Layer)合作进行事件的分发和输出。需要注意的是,集群中所有的

PN 都是对等的,没有中心节点,使得集群的部署和维护相对简单。

37

图 4.10 处理节点(PN)逻辑结构

图4.10展示了一个PN的逻辑结构。一个PN由PE容器(Processing Element Container,

PEC)、事件监听器(Event Listener)、分配器(Dispatcher)和输出器(Emitter)构成。

Event Listener 负责监听事件并转交给 PEC,再由 PEC 交给合适的 PE 来进行处理。当一

个事件到达 PN 后,如果该 PN 中没有合适的 PE 处理该事件,那么,PN 会触发一次 PE

原型克隆操作,生成一个能够处理该属性值的 PE 实例(PE instance)。

PEC 中可以含有若干个 PE,分别用来处理不同的事件。PE 处理完事件后根据其定义

的输出方法可以输出事件,该输出事件将交由 Dispatcher 与通讯层进行交互并由 Emitter

输出至对应的逻辑节点。

通讯层主要负责集群管理、自动故障恢复(failover)到备用节点、逻辑节点到物理节

点的映射等任务。通讯层隐藏了逻辑节点到物理节点的映射,使得 PN 发送消息时只需要关

心逻辑节点而不用关心物理节点。图 4.11 展示了通讯层的逻辑结构。

图 4.11 通讯层逻辑结构

(1)路由(Routing):配置文件中定义了 S4 集群所关心的 key 的集合。当事件到达

时,它会利用事件的 EventType、属性 key 和属性值来计算事件的哈希值,用以路由到指

定的 PN。此外,单个事件可能会被路由到多个 PN 中,用于负载均衡以及广播事件。

(2)负载均衡(Load Balancing):S4 支持动态负载均衡。

(3)故障恢复管理(Failover Management):S4 采用有损的故障恢复机制,后面会

详述该机制。

(4)传输协议(Transport Protocols):通讯层采用插件式的架构来为不同的事件选

择不同的网络协议。例如,对于控制消息,它会采用可靠方式(如 TCP)发送;而为了优

化集群的吞吐率,它可能会采用不可靠的方式(如 UDP)发送数据消息。

(5)Zookeeper:通讯层使用 ZooKeeper 在 S4 集群节点之间进行一致性协作管理。

ZooKeeper 是 Hadoop 下的开源子项目,主要为分布式应用提供分布式一致性协作服务。

4.3.2 系统特性

去中心化的对等架构:S4 中,所有节点都是对等的,没有担负特殊责任的中心节点,

因而没有单点故障问题,同时大大简化了部署和维护工作。

低延迟:S4 中,数据的存储和计算均在处理节点的本地内存中完成,避免了磁盘 I/O

瓶颈从而达到最小化延迟。

分布式、可扩展的架构:用户可以用多个普通的、廉价的机器来构建 S4 集群。并且,

S4 集群所支持的节点数没有上限。

不支持动态扩展:S4 不支持在集群运行的过程中动态地增减节点。

有损的故障恢复:当集群中某个活动节点因故障失效时,S4 会自动选取一个空闲节点

来替换失效的节点。但是,由于数据均存储在内存中,失效节点中的数据将全部丢失掉,这

即为有损的故障恢复。为了解决这个问题,S4 从 0.5.0 版本开始增加了一种检查点

38

(checkpointing)机制,来尽可能将状态的丢失最小化,如图 4.12 所示。该机制在每个 S4

节点中增加一个 checkpointing 框架,该框架将定时地获取 PEs 的状态等相关信息并存储到

远程的存储后端中。当该节点失效时,S4 则可以利用 checkpointing 框架中存储的信息将

节点恢复到之前的某个状态。

图 4.12 检查点机制

4.3.3 压力测试

S4 的开发小组对 S4 系统进行了一个压力测试,用于评估系统在远高于期望的事件流

量下的性能。实验所用的 S4 集群有 8 台服务器,每台服务器 4 个 64 位 CPU,16GB 内存。

S4 集群中运行了 16 个 PN(每个节点 2 个),事件由 300 万服务和点击组成。他们将离线

生成的事件流导向 S2 网格,以一个递增的事件流速率多次运行。在每次运行之后,将系统

估算的 CTR 的值和来自搜索 log 的实际 CTR 做比较。图 4.13 显示了这次测试的结果:S4

系统在事件到达速率为 10Mbps 左右时性能开始下降。下降的原因主要是,S4 的事件处理

速度赶不上事件到达速率,因此导致了事件丢失。

图 4.13 S4 压力测试

4.4 Storm 系统介绍

Storm[9]是 Twitter 开源的实时数据处理框架(原来是由 BackType 开发,后 BackType

被 Twitter 收购,将 Storm 作为 Twitter 的实时数据分析)。实时数据处理的应用场景很广

泛,如个性化搜索广告的会话特征分析。这种高可拓展性,能处理高频数据和大规模数据的

实时流计算解决方案将被应用于实时搜索,高频交易和社交网络上。而流计算并不是最近的

热点,金融机构的交易系统正是一个典型的流计算处理系统,它对系统的实时性和一致性有

很高要求。但 Storm 不只是一个传统的大数据分析系统,它还是复杂事件处理 (CEP) 系

统的一个示例。CEP 系统通常分类为计算和面向检测,其中每个系统都可通过用户定义的

算法在 Storm 中实现。

Twitter 列举了 storm 的三大作用领域:

39

(1) 信息流处理(Stream Processing):Storm 可以用来实时处理新数据和更新数

据库,兼具容错性和可扩展性。

(2) 连续计算(Continuous Computation):Storm 可以进行连续查询并把结果即时

反馈给客户,比如将 Twitter 上的热门话题发送到客户端。

(3) 分布式远程过程调用(Distributed RPC):Storm 可以用来并行处理密集查询,

Storm 的拓扑结构是一个等待调用信息的分布函数,当它收到一条调用信息后,会对查询进

行计算,并返回查询结果。

4.4.1 设计思想

在 Storm 中,认为 Stream 是一个不间断的、无界的连续元组。Storm 认为每个 stream

都有一个 stream 源,也就是原始元组的源头,所以它将这个源头抽象为 spout,spout 可能

是连接 twitter api 并不断发出 tweets,也可能是从某个队列中不断读取队列元素并装配为元

组发射。

同样的思想 twitter 将流的中间状态转换抽象为 bolt,bolt 可以消费任意数量的输入流,

只要将流方向导向该 bolt,同时它也可以发送新的流给其他 bolt 使用,这样一来,只要打开

特定的 spout 再将 spout 中流出的元组导向特定的 bolt,由 bolt 对导入的流做处理后再导向

其他 bolt 或者目的地。整个流程如图 4.14 所示:

图 4.14 Storm 流程图

我们可以很容易的理解这幅图,这是一张有向无环图,Storm 将这个图抽象为 Topology

即拓扑,拓扑是 storm 中最高层次的一个抽象概念,它可以被提交到 storm 集群执行,一个

拓扑就是一个流转换图,图中每个节点是一个 spout 或者 bolt,图中的边表示 bolt 订阅了哪

些流,当 spout 或者 bolt 发送元组到流时,它就发送元组到每个订阅了该流的 bolt。

4.4.2 系统架构

Storm 集群有两种节点:master 节点和 worker 节点。Master 节点运行一个称之为“nimbus”

的后台程序。Nimbus 负责在集群范围内分发代码、为 worker 节点分配任务和故障监测。每

个 worker 节点运行一个称之“supervisor”的后台程序。Supervisor 监听分配给它所在机器

的工作,基于 nimbus 分配给它的事情来决定启动或停止工作者进程。每个 worker 进程执行

一个 topology 的子集;一个运行中的 topology 由许多跨多个机器的工作者进程组成。一个

zookeeper 集群负责 nimbus 和多个 supervisor 之间的所有协调工作。系统架构如图 4.15 所示:

40

图 4.15 Storm 系统架构图

此外,nimbus 后台程序和 supervisor 后台程序都是快速失败(fail-fast)和无状态的,所

有状态维持在 zookeeper 或本地磁盘。这意味着用户可以结束 nimbus 进程和 supervisor 进程,

然后重启,系统将恢复状态并继续工作。这种设计中 master 并没有直接和 worker 通信,而

是借助中介 zookeeper,这样一来可以分离 master 和 worker 的依赖,将状态信息存放在

zookeeper 集群内以快速回复任何失败的一方。这种设计使 storm 极其稳定。

4.4.3 系统特性

Storm 具有如下系统特性:

(1)简单的编程模型:类似于 MapReduce 降低了并行批处理复杂性,Storm 降低了进

行实时处理的复杂性。

(2)可以使用各种编程语言:用户可以在 Storm 之上使用各种编程语言。默认支持

Clojure、Java、Ruby 和 Python。要增加对其他语言的支持,只需实现一个简单的 Storm 通信

协议即可。

(3)容错性:Storm 会管理工作进程和节点的故障。

(4)水平扩展:计算是在多个线程、进程和服务器之间并行进行的。

(5)可靠的消息处理:Storm 保证每个消息至少能得到一次完整处理。任务失败时,

它会负责从消息源重试消息。

(6)快速:系统的设计保证了消息能得到快速的处理,使用 ZeroMQ 作为其底层消息

队列。

(7)本地模式:Storm 有一个“本地模式”,可以在处理过程中完全模拟 Storm 集群。这让

用户可以快速进行开发和单元测试。

4.5 Puma 系统介绍

Puma[10]是 Facebook 支持开发的一款基于 Hive/Hadoop 的流式大数据计算引擎。

Facebook 提供给内容开发者的 Facebook Insights 工具选定了“HBase+Scribe+Ptail+Puma”

的解决方案,一方面解决了 Insights 系统可扩展的需求,另一方面很好的适应实时计算分

析的要求。

4.5.1 系统架构

总体上来说,HBase 可以将数据进行分布式存储,为可扩展性提供了基础;其次,该方

41

案设计的尾部标识架构,可以将产生的新事件以 log 文件的方式存储,并对 log 文件加上尾

部标识;整个系统可以将所有事件聚集起来并且存入 HBase 中;最后,利用用户界面可以将

数据提取出来,并且展示给用户。

Insights 的“HBase+Scribe+Ptail+Puma”整个解决方案中,每个部分都是由独立的系

统控制,各自协作,形成一条流水线的工作模式。本文先分别介绍这个解决方案各部分的主

要功能,然后再介绍其具体的数据流程。

(1) Data Freeway

图 4.16 Data Freeway 流程图

Data Freeway 是建立在 Scribe 和 HDFS 之上的一个可扩展的流数据处理框架,负责流

数据的采集和传输。Data Freeway 一共分为四个部分。

第一个部分是 Scribe,用于从各种日志源上收集日志,并通过 RPC 来发送数据。同时

Scribe 可以控制一些问题,如当 HDFS 出现问题时或者机器出现故障时,Scribe 会将日志转

存到本地或者另一个位置,当问题解决后,Scribe 会将转存的日志重新传输给 HDFS。其次,

Scribe 把 log 行写的极度精简,这意味着更多的 log 行可以被存储到主存中进行处理。

第二部分被称作 Calligraphus,它利用 zookeeper 去管理这些 log 文件的所属,并负

责把数据混合起来按照 datanode 的形式存储到 HDFS 中。具体来说,Calligraphus 主要负

责通过 RPC 取得 log 数据并写入文件系统。每个 log 分类都被表示成一个或者多个文件系统

的目录。每个目录都包含一系列有顺序的文件,并且以数据作为文件的名字。同时为了节省

空间,这些文件同时是可以被压缩的。Calligraphus 最有意思的一个特性就是 bucketing

support。这里设计了很多称为“应用桶”(Application Buckets),它们是按照应用所定义

的划分。这些桶将被用来划分log consumer。此时因为一些log流很大,对应的log consumers

需要被划分开来。另外,“基础桶”(Infrastructure Buckets)可以允许一个单独的“应用

桶”拥有从几 bytes 每秒到几十 GB 每秒的 log 流吞吐量的能力。每个“基础桶”都对应一

个目录,所以大的数据流可以同时流向多个目录。

第三部分是 Continuous copier,随着数据量不断的增大,它能持续性的把 HDFS 的文

件拷贝到另外的 HDFS 中。它比以批处理为基础的 mapreduce 拷贝好的地方就是低延迟和平

滑的网络用法。目前他被部署成一个长期运行的 map only 的工作模式,但是它可以很轻松

的被任何一个工作调度系统所调度。它现在在 HDFS 用锁定文件的方式去协调不同的结点。

以后将把它加入 zookeeper 管理。

42

图 4.17 PTail 处理机制

最后一部分是 PTail,它负责将数据从文件系统传输成一个输出的流。这部分最主要的

特征就是 checkpoint,它在每个目录上都包含当前所有的文件以及这些文件的一个偏移量

信息。这些允许 PTail 回滚到前一个 checkpoint 去重新产生数据流。用于防止数据重复或

数据丢失。

图 4.18 Data Freeway 通道机制

综上所述,整个 Data freeway 实时数据的分析提供了两个通道负责数据传输。不过值

得注意的是,通过 RPC 获取数据有更低的延迟,但当网络有问题会有一些数据损失,容错性并

不是很好,并在代码复杂度很低。通过文件系统获取数据有较长的延迟,但它没有任何损失或

重复,有很强的容错机制。问题是文件系统的代码,特别是 HDFS,非常复杂,并且仍然需要识

别和修复一些错误。

(2)Puma

Facebook 在一开始的时候设计了一个简单的流处理聚集引擎。Log 流在一个集群上做聚

集操作,并且把结果进行持久保存。在线的服务可以从存储器中获得结果,也可以通过聚集

直接获得。通常,因为只有一些合作网站的拥有者去访问这个引擎,所以导致系统写入的吞

吐量远远的大于读取量。

图 4.19 简单的流聚集引擎系统架构

利用这个架构,流聚集引擎系统每秒钟对 1M 的 log 流数据进行处理。针对每一条 log

流数据,系统需要将其按照不同的操作(如年龄、性别等)进行分组。每个组的第一个 Key

值经常是以时间或者数据相关的值为基础的,以至于结果经常在系统一段时间内变成静止的。

同时,此系统不能支持一些复杂的聚集操作,如特殊计数和高命中率查询操作。

43

此外在选取存储介质方面,Facebook 通过对比 MySQL 和 HBase 的特性发现,准备选取

HBase作为存储引擎很重要的一个原因就是 HBase相对于 MySQL来说在分布式的环境下管理

数据更简单。同时 HBase 写入的效率更高并且支持列存储。但是读取数据的效率是有瓶颈的。

通过对上述流数据聚集引擎的分析,Facebook 设计出了第一个针对 Insights 系统的流

数据处理框架——Puma2.

图 4.20 Puma2 系统架构

在部署 Puma2 时,系统利用 Data Freeway 中的 PTail 产生并提供多条并行的数据流。

对于每一个数据流,Puma2 发出一个“增加”的操作给 HBase。值得注意的是,Puma2 的服

务器是对称型的,Hbase 中的同一行可以同时被多个 Puma2 发出的操作所调用。因为 HBase

可以在同一行的多个列上做单值增加的操作,所以 Puma2 利用了这一特性去控制多个 group

by 的操作。

Puma2 是极度简单的设计并且易于维护,其最根本的原因就是 Puma2 的服务器之间是相

互对称,在大多数时间都处于休眠状态。唯一的状态就是每隔一段时间 Ptail 的 checkpoint

的信息被保存到 HBase。因此,Puma2 可以轻松的做到添加可操作的集群或者当集群中的某

个服务器当机时,直接重启即可。当然,Puma2 也有很多不足,首先,HBase 的“增加”操

作代价非常大,因为该操作是即读又写的,而频繁读的代价是很大的。同时,Puma2 不可能

支持除计数以外的其他聚集操作,因为这需要在 HBase 中嵌入很多自定义的代码。 最后,

由于 checkpoint 是在多个事务中写入的,Puma2 会产生一些数据重复。基于 Puma2 的局限

性,系统被做了一些改善。在 Puma2 的服务上,为了减少 HBase 的负载量,“增加”操作的

请求被以批处理的形式进行。但是由于 Group by 的 key 值的长尾分布,“增加”操作批处理

的效果并不好,而且会造成数据不精确。在 HBase 端,首先改善的便是通过减少锁的个数去

优化“增加”操作,另一个有效的改善是 HBase 中的短的循环读直接硬盘上的 HDFS 的块文

件读取数据,而非通过 DataNode 的守护进程。其次,Hbase 在高负载下的稳定性也得到了

一定的提升。

虽然通过改善,Puma2 的性能得到一些提升,但是效果并不显著。于是,Facebook 又设

计出了一个新的被成为 Puma3 的流数据处理引擎。其与 Puma2 最大的不同是 Puma3 中的聚集

操作是在主存当中,而非 HBase 中。

为了能够使流数据在内存中聚集,puma3 设计成以聚集 key 而分的区进行操作。这意味

着,PTail 输出的数据流必须也同时按照相应的 key 进行划分。数据流这部分的操作是通过

Calligraphus 中的应用桶完成的。

图 4.21 Puma3 系统架构

Puma 的每个划分区的内存中都有一个 hashmap。Hashmap 上的元组都是以聚集 key 和用

44

户定义的聚集操作组成的元组对,这些操作可以是计数,求和,求平均等等。HBase 是做永

久存储的,但是不经常从 HBase 里面读数据。

对于写的过程,对于每一个 log 流,Puma3 提取出所需要 key和 value 的列。用这些 key

去到内存查 hashmap,并把聚集方式当作 value。需要注意的是,因为 log 流已经按照聚集

key 进行了划分,所以相同的聚集 key 不会出现在多于一个的 puma3 处理中。这是 puma3 能

正常工作的关键。

对于 checkpoint 的工作流程来说,Puma3 每隔 5 分钟设置一个 puma3 操作的状态的

checkpoint。并把所有的修改过的 hashmap 的元组和 PTail checkpoint 都保存下来。 如果

puma3 crash 或者重启后,它可以从 Hbase 连续读取的相关信息进行恢复(连续读在 HBase

中很快的)。同时为了节省内存,一旦实时数据聚集的时间窗过去了,Puma3 就把数据清除

出内存,因为系统不会再接收到这段时间内传输的新的数据流了。

在读的过程上有两种选择。如果想读未提交的或者是正在处理的聚集操作,通常会有

10 秒左右的延迟,Puma3 直接通过内存中的 hashmap 进行聚集操作。如果想读的是提交过的

聚集操作,puma3 会直接从 HBase 中进行读取。需要注意的是,如果 puma3 操作过程中在设

定下一个 checkpoint 之前当机,那么未提交的这种聚集结果会比实际结果少。 所以在

serving 和 puma 中间设置一个缓存机制是必不可少的。

Puma3 写的吞吐量上比 Puma2 高的很多。而且只用到了 Puma2 的四分之一的集群去处理

同样的工作量。最主要的原因是 HBase 写的优势。然而,puma3 需要很大的内存,为了保证

log 流写入的能力,所有的聚集操作引起的变化也需要存在内存中。

4.5.2 系统特性

首先,Puma3 系统的流数据聚集操作是在内存中完成的。相对于在 HBase 中进行流数据

聚集操作,在内存中,流数据聚集的速度会大幅度提高,同时也会提高流数据处理的吞吐量

能力。以后,通过 SSD 的应用扩展,能将 Puma3 集群中每个机器扩展到 10 倍以上的流数据

处理的吞吐量。

第二,Puma3 最重要的一个特性之一就是 Puma3 定义了一套专门为其自身打造的流数据

查询语言。通过这种类 SQL 的查询语言,用户可以定义输入流、输出表,并且可以进行基本

的查询操作,同时,该查询操作包含用户自定义的一些聚集功能。

第三,Puma3 可以简单的支持一些特殊的近似聚集操作。对于一些独特的计数操作,

Puma3 部署了一个简单的自适应采样算法,随着数据的增加,样本聚集也会越来越精确,

Puma3 也可以轻松的实现标准的 bloom filter 计数。对于一些经常出现的项目,Puma3 计划

实现典型的损耗计算算法和概率损耗计算算法。

第四, Puma3 支持 HBASE 中静态表的 join 操作。但这个 join key 必须是 Hbase 表中

的 row key。对于用户定义的聚集操作,Puma3 将其以分布式哈希查找的方式进行执行,并

且通过本地的缓冲机制可以提高吞吐量。

最后,PTail的 Checkpoint机制能够保证 Puma3在接收流数据源时的不重复和不丢失。

并且将其延伸到 Puma3 的系统中来,确保系统在当机或者断电的突发情况下,能够有效的回

滚到之前的状态进行对流数据的处理。

4.6 Samza 系统介绍

Samza[11]是由 Linkedln 公司所开发的一个分布式流处理框架,专用于实时数据的处理,

非常像 Twitter 的流处理系统 Storm,近日 LinkedIn 于 2013 年 9 月开源了这项技术。

分布计算系统框架,按照数据集的特点来说,主要分为 data-flow 和 streaming 两种。

45

data-flow 主要是以数据块为数据源来处理数据,代表有:MR、Spark 等;而 streaming 主要

是处理单位内得到的数据,这种方式,更注重于实时性,主要包括 Strom、JStorm 和 Samza

等。

简单的讲,Samza是一个基于 Hadoop、建立在 YARN基础之上,而且底层使用了LinkedIn

自家的 Kafka 分布式消息系统的处理框架。这样的特点使得 Samza 既能充分利用 Hadoop 集

群的资源,做一些存储、离线分析的功能,又能将实时处理运行在 Hadoop 上,创造性的弥

补了传统流处理框架实时性的不足。

4.6.1 系统架构

Samza 的总体架构主要包含三层:流处理层、执行层、处理层,如图 4.22 所示。其中

流处理层使用了 Linkedln 自己开发的消息系统 Kafka;执行层则直接托管在 Hadoop 的 YARN

之上;而上层的处理层由 Samza 提供的 API 构成。

图 4.22 Samza 三层结构框架

这样的三层结构显然与基于 Hadoop 的系统架构有很大的相似之处(如图 4.23),只是

消息队列替代了文件系统,上层的处理层功能有所不同。

图 4.23 Hadoop 三层系统架构

下面我们将对这三个不同层次以及三层的交互进行逐一介绍。

(1) 流处理层

前文已经介绍了 Samza 的流处理层使用了 Linkedln 自家开发的分布式消息处理系统

Kafka,如图 4.24 所示,Kafka 是一个消息的发布和订阅系统,消息的发布可以称作为 producer、

消息的订阅可以表述为 consumer,将中间的存储陈列可以称为 broker。

图 4.24 Kafka 消息处理架构

46

Message(消息)是通信的基本单位,每个 Producer 可以向一个 topic(主题)发布一些

消息。如果 consumer 订阅了这个主题,那么新发布的消息就会广播给这些 consumer。 Kafka

是显式分布式的,多个 producer、consumer 和 broker 可以运行在一个大的集群上,作为一个

逻辑整体对外提供服务。对于 consumer,多个 consumer 可以组成一个 group,这个 message

只能传输给某个group中的某一个 consumer。producer和consumer通过 zookeeper去发现 topic

(主题),并通过 zookeeper 来协调生产和消费的过程。

Producer 在向流中产生消息的同时会对其赋予一个 key 值,Broker 会通过这一 key 值对流中

的不同消息进行划分,拥有不同 Key 值得消息会存储在不同的节点中,供 consumer 进行使

用。

不可否认 Kafka 是一个优秀的消息处理系统,它提供了消息传递的保障机制和具有高可

用性的消息划分,同时具有良好的可扩展性,实现了流式处理框架底层的许多核心基础架构,

把消息串联流动起来就是 Streaming 了。但是要构建一个可用的流式数据处理框架,还是有

许多事情要做。例如生产者和消费者进程的管理,作业调度和容错处理,辅助工具和监控管

理手段,更友好方便的用户接口等等,本质上说,Samza 是在消息队列系统上的更高层抽象,

是一种应用流式处理框架在消息队列系统上的一种应用模式的实现。

(2) 执行层

Samza 的执行层直接托管于 Hadoop 的下一代集群调度程序 YARN 之上。从业界使用分

布 式 系 统 的 变 化 趋 势 和 hadoop 框 架 的 长 远 发 展 来 看 , MapReduce 的

JobTracker/TaskTracker 机制需要大规模的调整来修复它在可扩展性,内存消耗,线程模型,

可靠性和性能上的缺陷。在过去的几年中,hadoop 开发团队做了一些 bug 的修复,但是最

近这些修复的成本越来越高,这表明对原框架做出改变的难度越来越大。

为从根本上解决旧 MapReduce 框架的性能瓶颈,促进 Hadoop 框架的更长远发展,从

0.23.0 版本开始,Hadoop 的 MapReduce 框架完全重构,发生了根本的变化。新的 Hadoop

MapReduce 框架命名为 MapReduceV2 或者叫 Yarn,其架构图如图 4.25 所示:

图 4.25 Yarn 架构

可以看出 YARN 提供了三种主要节点类型:NodeManager(NM)、ResourceManager(RM)

以及 ApplicationMaster(AM)。

其中 NodeManager(NM) 功能比较专一,就是负责 Container 状态的维护,并向 RM 保

持心跳; ResourceManager 是一个中心的服务,它做的事情是调度、启动每一个 Job 所属

的 ApplicationMaster、另外监控 ApplicationMaster 的存在情况;ApplicationMaster 负责一

47

个 Job 生命周期内的所有工作,类似老的框架中 JobTracker。

Container 是 Yarn 为了将来作资源隔离而提出的一个框架。目前仅仅提供 java 虚拟机

内存的隔离 ,hadoop 团队的设计思路应该后续能支持更多的资源调度和控制 , 既然资源表

示成内存量,那就没有了之前的 map slot/reduce slot 分开造成集群资源闲置的尴尬情况。

(3) 层间交互

介绍了 Samza 流处理层和执行层的具体情况之后,下面继续介绍三层之间是怎样通过

交互来协同工作的。如图 4.26 所示,Samza 处理层实质上提供了一个类似 YARN

ApplicationMaster 的用户接口,运行于 YARN 之外。当利用 Samza 进行开发时,开发人员

将数据流处理任务通过一个 Job 的形式递交到处理层,处理层的 API 将其传递至 YARN 上

独立进行处理,而 YARN 工作时需要的数据则来自于流处理层的消息系统 Kafka。

图 4.26 Samza 层间交互框架

图 4.27 详细说明了具体步骤。

图 4.27 Samza 层间交互具体流程

Samza 客户端向 YARN 的 ResourceManager 提交新的工作任务后, ResourceManager

访问 NodeManager 为任务分配空间, NodeManager 为任务分配空间后会重新访问

ApplicationMaster 以申请足够的 container 来保证任务的运行,而在任务运行过程中,为任务

提供输入输出流的 Kafka 可以被视为 YARN 的 NodeManager,如此三者协同一体,保证了

任务的顺利执行。

4.6.2 系统特性

Samza 是一个 Linkedln 开发的一个非常经典的小而美的项目,只有几千行代码,完成的

功能就可以和 Storm 媲美。Samza 的主要特性也正是体现在搭配使用 Kafka 和 YARN 所带来

的优势,包括以下几点:

(1)高容错:如果服务器或者处理器出现故障,Samza 将与 YARN 一起重新启动流处

48

理器。

(2)高可靠性:Samza 使用 Kafka 来保证所有消息都会按照写入分区的顺序进行处理,

绝对不会丢失任何消息。

(3)可扩展性:Samza 在各个等级进行分割和分布;Kafka 提供一个有序、可分割、

可重部署、高容错的系统;YARN 提供了一个分布式环境供 Samza 容器来运行。

(4)简易的用户接口:与大多数底层消息系统的 API 不同,Samza 为开发人员提供了

一个非常简易的类似于使用 Map/Reduce 的消息处理接口,这使得在 Samza 上所进行的上层

开发难度大大减小。

(5)良好的迁移性:Samza 的流处理层和执行层都是独立于 Samza 之外的,因此是可

插拔式的,并不仅仅局限于 YARN 和 Kafka,开发人员可以使用其他框架来替代,不局限于

上述两种技术。

4.7 小结

针对以上各个系统在分布性、高可靠性、容错性和可扩展性等特点,表 4.2 进行了对比

分析。

近年来,流式大数据处理技术已发展为现代数据库研究的主要方向之一,受到了数据库

领域和实时系统处理领域的极大关注。流数据管理系统需要对一系列的概念、理论、技术、

方法和机制进行深入研究,学术界和工业界开发出了多种适合自身需求的大规模数据流处理

系统。本节针对应用较为广泛的 Storm 和 S4 数据流处理系统,以及新推出的 Puma 和 Samza

数据流处理系统进行了归纳总结,并对各个系统的特点和性能进行了深入分析。这为今后进

行流数据管理的应用和研究奠定了基础。

表 4.2 系统对比分析

参考文献

[1] https://github.com/facebookarchive/scribe

[2] http://kafka.apache.org/

[3] http://flume.apache.org/

[4] https://chukwa.apache.org/

49

[5] http://sqoop.apache.org/

[6] http://www.rabbitmq.com/

[7] http://projects.spring.io/spring-xd/

[8] Neumeyer L, Robbins B, Nair A, Kesari A. S4: Distributed stream computing platform. In:

Proc. of the 10th IEEE Int’l Conf. on Data Mining Workshops (ICDMW 2010). Sydney: IEEE

Press, 2010. 170−177.

[9] http://storm-project.net/

[10] HiC2011 — Realtime data streams and Analytics-Data Freeway and Puma-Facebook. 2013.

http://ishare.iask.sina.com.cn/f/22023896.html

[11]http://samza.incubator.apache.org/