作者:高聪 王忠民 陈彦萍
来源:华章科技
大数据的生命周期分为数据获取(data acquisition)、数据存储(data storage)、数据分析(data analysis)以及结果(result),并且将前述大数据处理的三代技术中相关的工具映射至数据获取、数据存储和数据分析三个环节来进行分类讨论,详情如表1-2所示。
▲表1-2 大数据处理的典型工具
在表1-2中,三代技术中不同的处理阶段所涉及的工具存在重叠。此外,对于混合计算技术,其本身同时涉及批处理技术和实时处理技术,实现混合计算模型的技术也要比单纯的批处理技术和实时处理技术更加复杂;鉴于混合计算技术的上述特点,这里不对在数据的获取、存储与分析方面所涉及的具体工具做特别的划分。
Hadoop分布式文件系统(Hadoop Distributed File System,HDFS)目前是Apache Hadoop项目的一个子项目,与已有的分布式文件系统有很多相似之处。
此外,作为专门针对商业化硬件(commodity hardware)设计的文件系统,HDFS的独特之处也很明显:首先其具有很高的容错性,其次可以部署在较为廉价的硬件上,最后能够提供高吞吐量的应用数据访问能力。
对于终端用户而言,HDFS就是一个传统的文件系统,具有文件和目录的创建、修改、删除等常规操作。
HDFS采用主/从(Master/Slave)体系结构。单个HDFS集群仅包含一个名称节点(NameNode),其提供元数据服务,管理文件系统的命名空间(namespace),并引导用户对文件的访问。此外,单个HDFS集群可以包含多个数据节点(DataNode),数据节点负责管理与自身相关联的存储空间。
HDFS对外给出文件系统的命名空间作为用户对数据进行访存的接口。
在HDFS内部,单个文件通常被分割成多个块(block),这些块存储在一系列数据节点上。由名称节点在整个HDFS集群的命名空间上执行文件和目录的打开、读取和关闭等操作。文件的块与数据节点之间的映射也是由名称节点管理的。数据节点基于名称节点的指令来实施块的创建、复制和删除等。
Sqoop是一个在Hadoop和关系数据库服务器之间传送数据的工具,方便大量数据的导入导出工作,其支持多种类型的数据存储软件。
Sqoop的核心功能为数据的导入和导出。
Sqoop的一个显著特点是可以使用MapReduce将数据从传统的关系数据库导入到HDFS中。Sqoop作为一个通用性的工具,只需要在一个节点上安装,因此安装和使用十分便捷。
Flume是由Hadoop生态系统中著名的软件公司Cloudera于2011年发布,该软件能够支持分布式海量日志的采集、集成与传输,以实时的方式从数据发送方获取数据,并传输给数据接收方。
Flume具有两个显著的特点:可靠性和可扩展性。
Flume以Agent的方式运行,单个Agent包含Source、Channel和Sink三个组件,由Agent对数据进行收集,然后交付给存储机制。从多个数据源收集到的日志信息依次经过上述三个组件,然后存入HDFS或HBase中。因此,通过Flume可以将数据便捷地转交给Hadoop体系结构。
Scribe是由Facebook开发的分布式日志系统,在Facebook内部已经得到了广泛的应用。Scribe能够针对位于不同数据源的日志信息进行收集,然后存储至某个统一的存储系统,这个存储系统可以是网络文件系统(Network File System,NFS),也可以是分布式文件系统。
Scribe的体系结构由三部分组成:Scribe Agent、Scribe和Storage。
Scribe的日志收集行为只包括主动写入的日志,Scribe自身没有主动抓取日志的功能。因此,用户需要主动向Scribe Agent发送相关的日志信息。
HBase的全称为Hadoop Database,是基于谷歌BigTable的开源实现,其使用Hadoop体系结构中的HDFS作为基本的文件系统。谷歌根据BigTable的理念设计实现了谷歌文件系统GFS,但是该方案未开源。HBase可以称为BigTable的山寨版,是开源的。
HBase在Hadoop体系结构中的位置介于HDFS和MapReduce之间,其架构为主/从形式,内部的两个核心构件为Master和RegionServer。
HBase是建立在HDFS之上的分布式面向列的数据库,能够针对海量结构化数据实现随机的实时访问,其设计理念和运行模式都充分利用了HDFS的高容错性。
由于HBase是面向列的,因此它在数据库的表中是按照行进行排序的。在HBase中,所有的存储内容都是字节,任何要存储的内容都需要先转换成字节流的形式,此外数据库的行键值按照字节进行排序,同时形成了索引。
MapReduce是Hadoop体系结构中极为重要的核心构件之一。作为一个分布式的并行计算模型,MapReduce包含的两个单词分别具有特定的含义:“Map”表示“映射”;“Reduce”表示“归约”。上述两个概念的基本理念源于函数式编程语言(functional programming language)。
与传统的编程语言不同,函数式编程语言是一类非冯诺依曼式的程序设计语言,其编程范式的抽象程度很高,主要由原始函数、定义函数和函数型构成。
MapReduce的这种设计思想使分布式并行程序设计的难度得以简化,用户将已有的代码稍加修改就能够运行在分布式环境下。在实际应用场景中,大多数情况下收集到的大量多源异构数据都不具有特定的规律和特征。
MapReduce的工作过程能够在一定程度上将上述数据按照某种规律进行归纳和总结。在“Map”阶段,通过指定的映射函数提取数据的特征,得到的结果的形式为键值对 。在“Reduce”阶段,通过指定的归约函数对“Map”阶段得到的结果进行统计。对于不同的具体问题,所需要的归约函数的个数可能千差万别。
总体来说,MapReduce具有开发难度低、扩展性强和容错性高三个显著特点。尽管其分布式并行计算模型能大幅度提高海量数据的处理速度,但受限于大数据的规模,通常MapReduce的作业例程的执行时间为分钟级,随着数据量的增加,耗时若干天也很普遍。
Hive针对数据仓库来提供类似SQL语句的查询功能,其能够将以结构化形式存储的数据映射成数据库表,主要应用场景为多维度数据分析和海量结构化数据离线分析。Hive的体系结构主要包含用户接口、元数据存储、解释器、编译器、优化器和执行器。
虽然使用MapReduce也能够实现查询,但是对于逻辑复杂度高的查询,用户在实现时难度较大。Hive提供类似于SQL的语法接口,降低了学习成本,提高了开发效率。
Hive基于SQL的语法来定义名为HiveQL或HQL的查询语言,其支持常规的索引化和基本的数据查询,更重要的是能够将基于SQL的查询需求转化为MapReduce的作业例程。
除了自身具有的功能之外,用户可以在Hive中编写自定义函数,具体来说分为三种:
Pig是一个面向过程的高级程序设计语言,能够分析大型数据集,并将结果表示为数据流,其内置了多种数据类型,并且支持元组(tuple)、映射(map)和包(package)等范式。
Pig有两种工作模式:Local模式和MapReduce模式。
作为一种程序设计语言,Pig能够对数据进行加载、处理,并且存储获得的结果。Pig和Hive均能够简化Hadoop的常见工作任务。Hive通常应用在静态数据上,处理例行性的分析任务。
Pig比Hive在规模上更加轻量,其与SQL的结合使得用户能够使用比Hive更加简洁的代码来给出解决方案。与MapReduce相比,Pig在接口方面提供了更高层次的抽象,具有更多的数据结构类型。此外,Pig还提供了大量的数据变换操作,MapReduce在这方面比较薄弱。
Cascading是用JAVA语言编写成的开源库,能够脱离MapReduce来完成对复杂数据工作流的处理。该开源库提供的应用程序编程接口定义了复杂的数据流以及将这些数据流与后端系统集成的规则。此外,其还定义了将逻辑数据流映射至计算平台并进行执行的规则。
针对数据的提取、转换和加载(Extract Transform Load,ETL),Cascading提供了6个基本操作:
初级的ETL应用程序通常涉及数据和文件的复制,以及不良数据的过滤。针对多种不同数据源的输入文件,需要对它们进行合并。计数和平均是对数据和记录进行处理的常用操作。结合指的是将不同处理分支中的处理结果按照给定的规则进行结合。
与Hadoop类似,Spark也是一个针对大数据的分布式计算框架。Spark可以用来构建大规模、低延迟的数据处理应用程序。
相对于Hadoop,Spark的显著特点是能够在内存中进行计算,因此又称为通用内存并行计算框架,与MapReduce兼容,其主要构件包括SparkCore、SparkSQL、SparkStreaming、MLlib、GraphX、BlinkDB和Tachyon。
Hadoop存在磁盘I/O和序列化等性能瓶颈,在Spark的设计理念中,选用内存来存储Hadoop中存储在HDFS的中间结果。Spark兼容HDFS,能够很好地融入Hadoop体系结构,被认为是MapReduce的替代品。
根据Spark官方网站的数据,Spark的批处理速度比MapReduce提升了近10倍,内存中的数据分析速度则提升了近100倍。
Spark模型所特有的弹性分布式数据集(Resilient Distributed Dataset,RDD)使得针对数据的灾难恢复在内存和磁盘上都可以实现。
总体来说,Spark的编程模型具有以下四个特点:速度(speed)、简易(ease of use)、通用(generality)和兼容(runs everywhere)。
作为一个面向大规模数据的数据仓库工具,Shark最初是基于Hive的代码进行开发的。Hive在执行交互查询时需要在私有数据仓库上执行非常耗时的ETL操作,为了弥补这个性能问题,Shark成了Hadoop体系结构中的首个交互式SQL软件。
Shark支持Hive包含的查询语言、元存储、序列化格式以及自定义函数。后来,Hadoop体系结构中MapReduce本身的结构限制了Shark的发展,研究者们中止了Shark的研发,启动了Shark SQL这个新项目。Shark SQL是基于Spark的一个组件,提供了针对结构化数据的便捷操作,统一了结构化查询语言与命令式语言。
Shark在Spark的体系结构中提供了和Hive相同的HiveQL编程接口,因此与Hive兼容。通过Hive的HQL解析,将HQL转换成Spark上的RDD操作。
Kafka是一个分布式流处理平台(distributed streaming platform),最初由领英公司开发,使用的编程语言是Java和Scala。
Kafka支持分区(partition)和副本(replica),针对消息队列进行处理。消息传送功能包含连接服务(connection service)、消息的路由(routing)、传送(delivery)、持久性(durability)、安全性(security)和日志记录(log)。
Kafka的主要应用程序接口有如下四类:生产者(producer API)、消费者(consumer API)、流(stream API)和连接器(connector API)。
Kafka对外的接口设计理念是基于话题(topic)的,消息生成后被写入话题中,用户从话题中读取消息。单个的话题由多个分区构成,当系统性能下降时,通常的操作是增加分区的个数。
分区之间的消息互相独立,每个分区内的消息是有序的。新消息的写入操作在具体实现中为相应文件内容的追加操作,该方式具有较强的性能。由于一个话题可以包含多个分区,因此Kafka具有高吞吐量、低延迟的特性。
消息队列包含两个模型:点对点(point-to-point)和发布/订阅(publish/subscribe)。
Kestrel是由推特(Twitter)开发的开源中间件(middleware),使用的编程语言为Scala,其前身是名为Starling的轻量级分布式队列服务器,同样Kestrel也具有轻量化的特点。
Starling支持MemCache协议,其能够方便地构建网络访问队列。推特早期使用Starling来处理大量的队列消息,后来推特将基于Ruby语言的Starling项目进行重构,使用Scala语言将其重新实现,得到Kestrel。
在协议支持性方面,Kestrel支持三类协议:MemCache、Text和Thrift,其中MemCache协议没有完整地实现,仅支持部分操作。Kestrel本身运行在Java虚拟机(Java Virtual machine,JVM)上,针对Java的各类优化措施均可以使用。
为了改善性能,Kestrel中的队列存储在内存中,针对队列的操作日志保存在硬盘中。虽然Kestrel本身是轻量化的,但其具有丰富的配置选项,能够很方便地组成集群,集群中的节点互相之间是透明的,针对队列中消息获取的GET协议支持阻塞获取和可靠获取。
阻塞获取是指用户可以设置超时时间,在时间内有消息的话即刻返回,如果超时后还没有消息就结束等待。可靠获取是指队列服务器只有在收到用户明确的确认反馈后,才将相关的消息从队列中永久删除。
如果用户使用GET操作从队列获取消息后队列服务器马上将该消息从队列中删除,那么此后需要用户来确保该消息不会异常丢失,这对网络状态和系统运行的特定环境要求较为苛刻。因此,用户可以采用可靠获取的方式来消除上述疑虑。
Storm是使用Java和Clojure编写而成的分布式实时处理系统,其雏形是由Nathan Marz和BackType构建的,BackType是一家社交数据分析公司。2011年,推特收购BackType,并将Storm开源。
Storm的主要功能是针对持续产生的数据流进行计算,进而弥补了Hadoop体系结构对实时性支持的缺失。Storm的处理速度快,具有良好的可扩展性和容错性,其所处理的数据位于内存中。
用户在Storm中设计的计算图称为拓扑(topology),拓扑中包含主节点和从节点,且以集群的形式呈现。Storm的主/从体系结构是由两类节点实现的:控制节点(master node)和工作节点(worker node),调度相关的信息以及主从节点的重要工作数据都是由ZooKeeper集群来负责处理的。
拓扑中的数据在喷嘴(spout)之间传递,喷嘴把从外部数据源获取到的数据提供给拓扑,因此是Storm中流的来源。数据流中数据的格式称为元组(tuple),具体来说为键值对(key-value pair),元组用来封装需要处理的实际数据。
针对数据流的计算逻辑都是在螺栓(bolt)中执行的,具体的处理过程中除了需要指定消息的生成、分发和连接,其余的都与传统应用程序类似。
Trident是位于Storm已有的实时处理环境之上更高层的抽象构件,提供了状态流处理和低延迟的分布式查询功能,其屏蔽了计算事务处理和运行状态管理的细节。此外,还针对数据库增加了更新操作的原语。
在Trident中,数据流的处理按照批次进行,即所谓的事务。一般来说,对于不同的数据源,每个批次的数据量的规模可达数百万个元组。一个处理批次称为一个事务,当所有处理完成之后,认为该事务成功结束;当事务中的一个或者多个元组处理失败时,整个事务需要回滚(rollback),然后重新提交。
Trident的事务控制包含三个层次:非事务控制(non-transactional)、严格的事务控制(transactional)和不透明的事务控制(opaque-transactional)。
上述针对消息的可靠性保障机制使得数据的处理有且仅有一次,保证了事务数据的持久性。容错机制使得失败的元组在重试环节的状态更新是幂等的,幂等性是统计学中的一个重要性能指标,其保证了即使数据被多次处理,从处理结果的角度来看和处理一次是相同的。
Trident的出现显著减少了编写基于Storm的应用程序的代码量,其本身具有函数、过滤器、连接、分组和聚合功能。在组件方面,它保留了Spout,将Bolt组件中实现的处理逻辑映射为一些新的具体操作,例如过滤、函数和分组统计等。
数据的状态可以保存在拓扑内部存储当中(例如内存),也可以保存在外部存储当中(例如磁盘),Trident的应用程序接口支持这两种机制。
S4项目是由雅虎(Yahoo)提出的,作为一个分布式流处理计算引擎,其设计的初衷是与按点击数付费的广告结合,基于实时的计算来评估潜在用户是否可能对广告进行点击。
这里S4是指简单的(Simple)、可扩展的(Scalable)、流(Streaming)以及系统(System)。在S4项目提出之前,雅虎已经拥有了Hadoop,但Hadoop的基本理念是批处理,即利用MapReduce对已经过存储的静态数据进行处理。尽管MapReduce的处理速度非常快,但是从本质上说,其无法处理流数据。
S4项目将流数据看作事件,其具体的实现中包含五个重要构件:处理节点(processing element)、事件(event)、处理节点容器(Processing Element Container,PEC)、机器节点(node)和机器节点集群(cluster)。
一个集群中包含多个机器节点,一个机器节点中包含一个处理节点容器,一个处理节点容器中包含多个处理节点。处理节点对事件进行处理,处理结果作为新的事件,其能够被其他处理节点处理。上述的点击付费广告的应用场景具有很高的实时性要求,而Hadoop无法很好地应对这样的要求。
具体来说,MapReduce所处理的数据是保存在分布式文件系统上的,在执行数据处理任务之前,MapReduce有一个数据准备的过程,需要处理的数据会按照分块依次进行运算,不同的数据分块大小可以对所谓的实时性进行调节。
当数据块较小时,可以获得一定的低延迟性,但是数据准备的过程就会变得很长;当数据块较大时,数据处理的过程无法实现较低的延迟性。诸如S4的流计算系统所处理的数据是实时的流数据,即数据源源不断地从外部数据源到达处理系统。
流计算处理系统的主要目标是在保证给定的准确度和精确性的前提下以最快的速度完成数据的处理。如果流数据不能够被及时处理,那么其潜在的价值就会大打折扣,随着处理时间的增长,流数据的潜在价值保持递减。软件开发者能够根据不同的场景和需求在S4的上层开发处理流数据的应用程序。
作为Spark的组成部分,Spark Streaming主要针对流计算任务,其能够与Spark的其他构件很好地进行协作。
一般来说,大数据的处理有两类方式:批处理和流计算。
作为Spark基础应用程序接口的扩展,Spark Streaming能够从众多第三方应用程序获得数据,例如Kafka、Flume和Kinesis等。在Spark Streaming中,数据的抽象表示是以离散化的形式组织的,即DStreams。DStreams可以用来表示连续的数据流。
在Spark Streaming的内部,DStreams是由若干连续的弹性数据集(Resilient Distributed Dataset,RDD)构成的,每个弹性数据集中包含的数据都是来源于确定时间间隔。Spark Streaming的数据处理模式是对确定时间间隔内的数据进行批处理。
由于部分中间结果需要在外存中进行存储,因此传统的批处理系统一般运行起来较为缓慢,但是这样的处理模式可以具有很高的容错性。
Spark Streaming的数据处理模式是基于弹性数据集进行的,通常将绝大部分中间结果保存在内存中,可以根据弹性数据集之间的互相依赖关系进行高速运算。这样的处理模式也被称为微批次处理架构,具体的特点是数据处理的粒度较为粗糙,针对每个选定的弹性数据集进行处理,对于批次内包含的数据无法实现进一步的细分。
2013年,项目负责人Rubén Casado在巴塞罗那的NoSQL Matters大会上发布了Lambdoop框架。Lambdoop是一个结合了实时处理和批处理的大数据应用程序开发框架,其基于Java语言。
Lambdoop中可供选择的处理范式(processing paradigm)有三种:非实时批处理、实时流处理和混合计算模型。
Lambdoop实现了一个基于Lambda的体系结构,该结构为软件开发者提供了一个抽象层(abstraction layer),使用与Lambda架构类似的方式来开发大数据相关的应用程序。
对于使用Lambdoop应用程序开发框架的用户,软件开发者在应用程序的开发过程中不需要处理不同技术、参数配置和数据格式等烦琐的细节问题,只需要使用必需的应用程序接口。
此外,Lambdoop还提供了辅助的软件工具,例如输入/输出驱动、数据可视化接口、聚类管理工具以及大量人工智能算法的具体实现。大多数已有的大数据处理技术关注于海量静态数据的管理,例如前述的Hadoop、Hive和Pig等。此外,学界和业界也对动态数据的实时处理较为关注,典型的应用软件有前述的Storm和S4。
由于针对海量静态数据的批处理能够考虑到更多相关信息,因此相应的处理结果具有更高的可靠性和健壮性,例如训练出更加精确的预测模型。遗憾的是,绝大多数批处理过程耗时较长,在对响应时间要求较高的应用领域,批处理是不可行的。
从理论上来说,实时处理能够解决上述问题,但实时处理有一个重大的缺陷:由于需要保证较小的延迟,实时处理所分析的数据量是十分有限的。在实际的生产环境中,通常需要实时处理和批处理两种方式各自具有的优点,这对软件开发者来说是一个挑战性的难题,同时这也是Lambdoop的设计初衷。
SummingBird是由推特于2013年开源的数据分析工具,大数据时代的数据处理分为批处理和实时处理两大领域,这两种方式各有利弊,仅采用一种处理方式无法满足各类应用日益多样化的需求。
作为能够处理大规模数据的应用软件,SummingBird的设计初衷是将上述两种处理方式结合起来,最大限度地获得批处理技术提供的容错性和实时处理技术提供的实时性,其支持批处理模式(基于Hadoop/MapReduce)、流处理模式(基于Storm)以及混合模式。SummingBird最大的特点是无缝融合了批处理和流处理。
推特通过SummingBird整合批处理和流处理来降低在处理模式之间转换带来的开销,提供近乎原生Scala和Java的方式来执行MapReduce任务。
SummingBird作业流程包含两种形式的数据:流(stream)和快照(snapshot),前者记录了数据处理的全部历史,后者为作业系统在单个时间戳上的快照。
简单地说,SummingBird可以认为是Hadoop和Storm的结合,具体包含以下构件:
关于作者:高聪,男,1985年11月生,西安电子科技大学计算机科学与技术专业学士,计算机系统结构专业硕士、博士。自2015年12月至今,在西安邮电大学计算机学院任教,主要研究方向:数据感知与融合、边缘计算和无线传感器网络。
本文摘编自《工业大数据融合体系结构与关键技术》,经出版方授权发布。