实时数据相关产品技术对比介绍
1 前言
本文介绍的相关产品主要针对实时数据的处理这一应用方向,包括各种消息中间件的介绍以及实时数据处理框架的介绍。首先通过概念梳理,了解当前流行的产品技术,分析相互关系、定位;再依次介绍各个产品的能力和特点,分析优缺点;最终根据产品技术的进行。
2 主要概念
l 消息中间件
消息中间件利用高效可靠的消息传递机制进行平台无关的数据交流,并基于数据通信来进行分布式系统的集成。通过提供消息传递和消息排队模型,它可以在分布式环境下扩展进程间的通信。
l 实时数据处理
实时数据处理包括对接收到的实时数据进行处理、分析的过程。数据规模巨大,需要利用大数据技术高效的分布式的方式快速完成分析,达到近似实时的效果,更及时的反映数据的价值和意义。
l 消息总线
消息总线是一种通信工具,可以在机器之间互相传输消息、文件等。消息总线扮演着一种消息路由的角色,拥有一套完备的路由机制来决定消息传输方向。发送段只需要向消息总线发出消息而不用管消息被如何转发,为了避免消息丢失,部分消息总线提供了一定的持久化存储和灾备的机制。
消息中间件更多的表述产品技术或者某个技术组件,如Kafka;消息总线是一个架构能力,因此下文介绍的部分产品将以消息中间件的概念作为定义。
l Ack
Ack是消息服务中一种消息接收确认机制,即在TCP/IP协议中,如果接收方成功的接收到数据,那么会回复一个ACK数据。通常ACK信号有自己固定的格式,长度大小,由接收方回复给发送方。其格式取决于采取的网络协议。当发送方接收到ACK信号时,就可以发送下一个数据。如果发送方没有收到信号,那么发送方可能会重发当前的数据包,也可能停止传送数据。具体情况取决于所采用的网络协议。
3 产品技术介绍
目前业界普遍使用的与实时数据相关的产品技术有很多,这些技术可以分为消息中间件、实时数据处理框架、分布式处理架构几类:消息中间件。负责消息的传递,主要产品包括ActiveMQ、Rabbitmq、ZeroMQ、Kafka等国外产品,也包括阿里使用的Notify和MetaQ。实时数据处理框架。提供分布式的针对实时流数据的计算能力的框架,主要包括Apache发布的Storm、Spark和Samza。分布式处理架构。以上设计分布式数据处理的产品中主要应用了Hadoop。
这些技术并不是同级别的,并不是因为他们都作为用来处理实时数据的工具,就把他们当做同类产品进行使用。消息中间件专注消息的传递,提供基础的数据接收、订阅、分发等能力;实时数据处理框架包含了消息传递的能力,比如:Storm中包含了ZeroMQ作为消息中间件,Samza配套了Kafka,但同时实时数据处理框架还提供了分布式的实时数据计算的架构和配套组件,更专注与计算和处理,其中Hadoop也是作为某些框架的一个组件,用于处理分析存储下来的实时数据。
实时数据处理框架和消息中间件所解决的问题和具备能力范围不同,实时数据处理框架包含的技术和能力范围要大于消息中间件和Hadoop。理解了这些技术的关系,下面分别介绍各个产品的技术特点。
3.1 消息中间件
3.1.1 ActiveMQ
ActiveMQ 是Apache出品的开源消息总线。ActiveMQ 是一个完全支持JMS1.1和J2EE 1.4规范的 JMS Provider实现,尽管JMS规范出台已经是很久的事情了,但是JMS在当今的J2EE应用中间仍然扮演着特殊的地位。
产品特点:
⒈多种语言和协议编写客户端。语言:Java,C,C++,C#,Ruby,Perl,Python,PHP。应用协议: OpenWire,StompREST,WS Notification,XMPP,AMQP
⒉ 完全支持JMS1.1和J2EE 1.4规范(持久化,XA消息,事务)
⒊ 对Spring的支持,ActiveMQ可以很容易内嵌到使用Spring的系统里面去,而且也支持Spring2.0的特性
⒋通过了常见J2EE服务器(如Geronimo,JBoss 4,GlassFish,WebLogic)的测试,其中通过JCA 1.5resource adaptors的配置,可以让ActiveMQ可以自动的部署到任何兼容J2EE 1.4 商业服务器上
⒌ 支持多种传送协议:in-VM,TCP,SSL,NIO,UDP,JGroups,JXTA
⒍ 支持通过JDBC和journal提供高速的消息持久化
⒎ 从设计上保证了高性能的集群,客户端-服务器,点对点
⒏ 支持Ajax
⒐ 支持与Axis的整合
⒑ 可以很容易得调用内嵌JMS provider,进行测试
3.1.2 ZeroMQ
Twitter的Storm 0.9.0以前的版本中默认使用ZeroMQ作为数据流的传输(Storm从0.9版本开始同时支持ZeroMQ和Netty作为传输模块)。
ZeroMQ号称是最快的消息队列,由于它支持的模式非常多:tcp、ipc、inproc、multicas,基本已经达到了替代标准socket的地步了。与 RabbitMQ 相比,ZMQ 并不像是一个传统意义上的消息队列服务器,事实上,它也根本不是一个服务器,它更像是一个底层的网络通讯库,在 Socket API 之上做了一层封装,将网络通讯、进程通讯和线程通讯抽象为统一的API 接口。
ZeroMQ是一个智能传输层,它并不是对socket的封装,而是在其之上有一套自己的协议。他跟 Socket 的区别是:普通的 socket 是端到端的(1:1的关系),而zeromq却是可以N:M 的关系,人们对 BSD 套接字的了解较多的是点对点的连接,点对点连接需要显式地建立连接、销毁连接、选择协议(TCP/UDP)和处理错误等,而ZeroMQ屏蔽了这些细节,让你的网络编程更为简单。ZeroMQ用于 node 与 node 间的通信,node 可以是主机或者是进程。可以使用非常丰富的开发模式像扇出(fanout)、发布订阅(pub-sub)、任务分发(task distribution)、请求响应(request-reply)等。
ZeroMQ具有一个独特的非中间件的模式,你不需要安装和运行一个消息服务器或中间件,因为你的应用程序将扮演这个服务器角色。你只需要简单的引用ZeroMQ程序库,可以使用NuGet安装,然后你就可以愉快的在应用程序之间发送消息了。
总之ZeroMQ是一种基于消息队列的多线程网络库,其对套接字类型、连接处理、帧、甚至路由的底层细节进行抽象,提供跨越多种传输协议的套接字。ZeroMQ是网络通信中新的一层,介于应用层和传输层之间(按照TCP/IP划分),其是一个可伸缩层,可并行运行,分散在分布式系统间。
3.1.2.1 ZeroMQ支持的消息模型
ZeroMQ将消息通信分成4种模型,分别是一对一结对模型(Exclusive-Pair)、请求回应模型(Request-Reply)、发布订阅模型(Publish-Subscribe)、推拉模型(Push-Pull)。这4种模型总结出了通用的网络通信模型,在实际中可以根据应用需要,组合其中的2种或多种模型来形成自己的解决方案。
l 一对一结对模型
最简单的1:1消息通信模型,可以认为是一个TCPConnection,但是TCP Server只能接受一个连接。数据可以双向流动,这点不同于后面的请求回应模型。
l 请求回应模型
由请求端发起请求,然后等待回应端应答。一个请求必须对应一个回应,从请求端的角度来看是发-收配对,从回应端的角度是收-发对。跟一对一结对模型的区别在于请求端可以是1~N个。该模型主要用于远程调用及任务分配等。Echo服务就是这种经典模型的应用。
图请求回应模型
l 发布订阅模型
发布端单向分发数据,且不关心是否把全部信息发送给订阅端。如果发布端开始发布信息时,订阅端尚未连接上来,则这些信息会被直接丢弃。订阅端未连接导致信息丢失的问题,可以通过与请求回应模型组合来解决。订阅端只负责接收,而不能反馈,且在订阅端消费速度慢于发布端的情况下,会在订阅端堆积数据。该模型主要用于数据分发。天气预报、微博明星粉丝可以应用这种经典模型。
图 发布订阅模型
l 推拉模型
Server端作为Push端,而Client端作为Pull端,如果有多个Client端同时连接到Server端,则Server端会在内部做一个负载均衡,采用平均分配的算法,将所有消息均衡发布到Client端上。与发布订阅模型相比,推拉模型在没有消费者的情况下,发布的消息不会被消耗掉;在消费者能力不够的情况下,能够提供多消费者并行消费解决方案。该模型主要用于多任务并行。
图 推拉模型
3.1.2.2 通信协议
提供进程内、进程间、机器间、广播等四种通信协议。通信协议配置简单,用类似于URL形式的字符串指定即可,格式分别为inproc://、ipc://、tcp://、pgm://。ZeroMQ会自动根据指定的字符串解析出协议、地址、端口号等信息。
3.1.2.3 优点
l 仅仅提供24个API接口,风格类似于BSDSocket。
l 处理了网络异常,包括连接异常中断、重连等。
l 改变TCP基于字节流收发数据的方式,处理了粘包、半包等问题,以msg为单位收发数据,结合Protocol Buffers,可以对应用层彻底屏蔽网络通信层。
l 对大数据通过SENDMORE/RECVMORE提供分包收发机制。
l 通过线程间数据流动来保证同一时刻任何数据都只会被一个线程持有,以此实现多线程的“去锁化”。
l 通过高水位HWM来控制流量,用交换SWAP来转储内存数据,弥补HWM丢失数据的缺陷。
l 服务器端和客户端的启动没有先后顺序。
l 支持多种通信协议,可以灵活地适应多种通信环境,包括进程内、进程间、机器间、广播。
l 支持多种消息模型,消息模型之间可以相互组合,形成特定的解决方案。
l 跨平台 支持Linux、Windows、OS X等。
l 多语言可以绑定C、C++、Java、.NET、Python等30多种开发语言。
l 高性能 相对同类产品,性能卓越。
3.1.2.4 缺点
l 消息无法持久化,除非自己在实现一个中间件,否则消息传递完成就删除了;
l 扩展性不是很好,其实是一个消息库,并不算是MQ;
3.1.3 Kafka
Kafka是一种高吞吐量的分布式发布订阅消息系统,它可以处理消费者规模的网站中的所有动作流数据。 这种动作(网页浏览,搜索和其他用户的行动)是在现代网络上的许多社会功能的一个关键因素。这些数据通常是由于吞吐量的要求而通过处理日志和日志聚合来解决。 对于像Hadoop的一样的日志数据和离线分析系统,但又要求实时处理的限制,这是一个可行的解决方案。Kafka的目的是通过Hadoop的并行加载机制来统一线上和离线的消息处理,也是为了通过集群机来提供实时的消费。
生产者向某个队列发送一个数据,消费者订阅一个队列,一旦这个队列内产生新的数据了,中间人就会将数据发送给所有订阅队列的消费者。
用术语来说生产者就是producer、消费者就是consumer、中间人就是broker,kafka主要就是这三者之间进行联系的。
3.1.3.1 优点
l 完全的分布式系统,能够以集群进行处理,Broker、Producer、Consumer都原生自动支持分布式,自动实现负载均衡;
l 通过O(1)的磁盘数据结构提供消息的持久化,这种结构对于即使数以TB的消息存储也能够保持长时间的稳定性能。
l 高吞吐量:在一台普通的服务器上既可以达到10W/s的吞吐速率;
l 支持通过Kafka服务器和消费机集群来分区消息。
l 支持Hadoop并行数据加载。对于像Hadoop的一样的日志数据和离线分析系统,但又要求实时处理的限制,这是一个可行的解决方案。Kafka通过Hadoop的并行加载机制统一了在线和离线的消息处理。
3.1.3.2 缺点
l 不支持事务;
l 不支持消息确认ack
3.1.4 Rabbitmq
Rabbitmq是流行的开源消息队列系统,使用erlang语言进行开发。RabbitMQ是AMQP(高级消息队列协议)的标准实现。可以说从功能上rabbitmq基本上是符号这次项目要求的工具。
3.1.4.1 优点
l 完整的消息队列系统,支持多种消息队列模式,包括竞争消费;
l 基于AMQP
l 支持集群模式,扩展集群容量和性能比较方便,同时集成了集群的监控和管理;
l 支持消息的持久化;
3.1.4.2 缺点
l 相对ZeroMQ性能不是特别理想大概在1wqps左右;
3.1.5 Redis
Redis是一个基于Key-Value对的NoSQL数据库,开发维护很活跃。虽然它是一个Key-Value数据库存储系统,但它本身支持MQ功能,所以完全可以当做一个轻量级的队列服务来使用。可以把Redis当做一个快速、稳定的发布/订阅的信息系统。
不支持ack确认机制。
3.2 实时数据处理框架
3.2.1 Apache Storm
Storm 是Twitter发布的一个开源的、大数据处理系统,与其他系统不同,它旨在用于分布式实时处理且与语言无关。
Storm为分布式实时计算提供了一组通用组件,可被用于“流处理”之中,实时处理消息并更新数据库。这是管理队列及工作者集群的另一种方式。Storm也可被用于“连续计算”(continuous computation),对数据流做连续查询,在计算时就将结果以流的形式输出给用户。它还可被用于“分布式RPC”,以并行的方式运行昂贵的运算。
Storm可以方便地在一个计算机集群中编写与扩展复杂的实时计算,Storm用于实时处理,就好比 Hadoop 用于批处理。Storm保证每个消息都会得到处理,而且它很快——在一个小集群中,每秒可以处理数以百万计的消息。可以使用任意编程语言来做开发。
在Storm中,先要设计一个用于实时计算的图状结构,我们称之为拓扑(topology)。这个拓扑将会被提交给集群,由集群中的主控节点(master node)分发代码,将任务分配给工作节点(worker node)执行。一个拓扑中包括spout和bolt两种角色,其中spout发送消息,负责将数据流以tuple元组的形式发送出去;而bolt则负责转换这些数据流,在bolt中可以完成计算、过滤等操作,bolt自身也可以随机将数据发送给其他bolt。由spout发射出的tuple是不可变数组,对应着固定的键值对。
3.2.2 Apache Spark
Spark Streaming是核心Spark API的一个扩展,它并不会像Storm那样一次一个地处理数据流,而是在处理前按时间间隔预先将其切分为一段一段的批处理作业。Spark针对持续性数据流的抽象称为DStream(DiscretizedStream),一个DStream是一个微批处理(micro-batching)的RDD(弹性分布式数据集);而RDD则是一种分布式数据集,能够以两种方式并行运作,分别是任意函数和滑动窗口数据的转换。
3.2.3 Apache Samza
Samza处理数据流时,会分别按次处理每条收到的消息。Samza的流单位既不是元组,也不是Dstream,而是一条条消息。在Samza中,数据流被切分开来,每个部分都由一组只读消息的有序数列构成,而这些消息每条都有一个特定的ID(offset)。该系统还支持批处理,即逐次处理同一个数据流分区的多条消息。Samza的执行与数据流模块都是可插拔式的,尽管Samza的特色是依赖Hadoop的Yarn(另一种资源调度器)和Apache Kafka。
4 产品技术对比
4.1 消息中间件
l RabbitMQ
RabbitMQ是本身支持很多的协议:AMQP,XMPP, SMTP,STOMP,也正因如此,它非常重量级,更适合于企业级的开发。
l Redis
通过入队和出对的对比测试,当数据比较小时Redis的入队性能要高于RabbitMQ,而如果数据大小超过了10K,Redis则慢的无法忍受;出队时,无论数据大小,Redis都表现出非常好的性能,而RabbitMQ的出队性能则远低于Redis。
l ZeroMQ
ZeroMQ能够实现RabbitMQ不擅长的高级/复杂的队列,但是开发人员需要自己组合多种技术框架,技术上的复杂度是对这MQ能够应用成功的挑战。但是ZeroMQ仅提供非持久性的队列,也就是说如果宕机,数据将会丢失。
l ActiveMQ
ActiveMQ类似于ZeroMQ,它能够以代理人和点对点的技术实现队列。同时类似于RabbitMQ,它少量代码就可以高效地实现高级应用场景。
l Kafka/Jafka
Kafka是Apache下的一个子项目,而Jafka是在Kafka之上孵化而来的,即Kafka的一个升级版。具有以下特性: Apache Kafka相对于ActiveMQ是一个非常轻量级的消息系统,除了性能非常好之外,还是一个工作良好的分布式系统。
l 综合特性对比
产品 | ActiveMq | ZeroMQ | RabbitMq | Kafka |
producer容错,是否会丢数据 | 通过持久化保证不丢失 | 发布订阅模型。如果发布端开始发布信息的时候,订阅端尚未连接上来,这些信息直接丢弃。不过一旦订阅端连接上来,中间会保证没有信息丢失。 | 有ack模型,也有事务模型,保证至少不会丢数据。ack模型可能会有重复消息,事务模型则保证完全一致 | 批量形式下,可能会丢数据。 非批量形式下, 1. 使用同步模式,可能会有重复数据。 2. 异步模式,则可能会丢数据。 |
consumer容错,是否会丢数据 | 通过持久化保证不丢失 | 没有ack模型 | 有ack模型,数据不会丢,但可能会重复处理数据。 | 批量形式下,可能会丢数据。非批量形式下,可能会重复处理数据。(ZK写offset是异步的) |
架构模型 | 基于JMS协议 | ZeroMQ将消息通信分成4种模型,分别是一对一结对模型(Exclusive-Pair)、请求回应模型(Request-Reply)、发布订阅模型(Publish-Subscribe)、推拉模型(Push-Pull) | 基于AMQP模型,比较成熟,但更新超慢。RabbitMQ的broker由Exchange,Binding,queue组成,其中exchange和binding组成了消息的路由键;客户端Producer通过连接channel和server进行通信,Consumer从queue获取消息进行消费(长连接,queue有消息会推送到consumer端,consumer循环从输入流读取数据)。rabbitMQ以broker为中心; | producer,broker,consumer,以consumer为中心,消息的消费信息保存的客户端consumer上,consumer根据消费的点,从broker上批量pull数据; |
吞吐量 | 不如Kafka | 高吞吐量、低延迟 | rabbitMQ在吞吐量方面稍逊于kafka,他们的出发点不一样,rabbitMQ支持对消息的可靠的传递。 | kafka具有高的吞吐量,数据的存储和获取是本地磁盘顺序批量操作,具有O(1)的复杂度,消息处理的效率很高 |
持久化 | 支持 | 不支持 | 支持 | 支持 |
可用性 | Master/Slave,一个broker作为Master提供服务,而其他broker则作为slave等待master失效从而顶上。 | 只是提供了重连机制,没有可靠性的设计。 | rabbitMQ支持miror的queue,主queue失效,miror queue接管 | kafka的broker支持主备模式 |
消息确认 | 支持 | 不支持 | 支持 | 不支持 |
支持事务 | 支持 | 不支持 | 支持 | 不支持 |
批量处理 | 不支持 | 不支持 | 不支持 | 支持 |
存储 | 磁盘 | 不支持 | 内存或者硬盘 | 磁盘,文件存储 |
集群负载均衡 | 支持broker的cluster | 不支持 | rabbitMQ的负载均衡需要单独的loadbalancer进行支持 | kafka采用zookeeper对集群中的broker、consumer进行管理,可以注册topic到zookeeper上;通过zookeeper的协调机制,producer保存对应topic的broker信息,可以随机或者轮询发送到broker上;并且producer可以基于语义指定分片,消息发送到broker的某分片上 |
4.2 实时数据处理框架
4.2.1 共同之处
Apache的实时数据处理框架Storm、Spark、Samza三种实时计算系统都是开源的分布式系统,具有低延迟、可扩展和容错性诸多优点,它们的共同特色在于:允许你在运行数据流代码时,将任务分配到一系列具有容错能力的计算机上并行运行。此外,它们都提供了简单的API来简化底层实现的复杂程度。
三种框架的术语名词不同,但是其代表的概念十分相似:
对比图
4.2.2 不同之处
下面表格总结了一些不同之处:
数据传递形式分为三大类:
1. 最多一次(At-most-once):消息可能会丢失,这通常是最不理想的结果。
2. 最少一次(At-least-once):消息可能会再次发送(没有丢失的情况,但是会产生冗余)。在许多用例中已经足够。
3. 恰好一次(Exactly-once):每条消息都被发送过一次且仅仅一次(没有丢失,没有冗余)。这是最佳情况,尽管很难保证在所有用例中都实现。
另一个方面是状态管理:对状态的存储有不同的策略,Spark Streaming将数据写入分布式文件系统中(例如HDFS);Samza使用嵌入式键值存储;而在Storm中,或者将状态管理滚动至应用层面,或者使用更高层面的抽象Trident。
4.2.3 分析
这三种框架在处理连续性的大量实时数据时的表现均出色而高效,那么使用哪一种呢?选择时并没有什么硬性规定,最多就是几个指导方针。
l Storm
如果你想要的是一个允许增量计算的高速事件处理系统,Storm会是最佳选择。它可以应对你在客户端等待结果的同时,进一步进行分布式计算的需求,使用开箱即用的分布式RPC(DRPC)就可以了。最后的但同样重要的原因:Storm使用Apache Thrift,你可以用任何编程语言来编写拓扑结构。如果你需要状态持续,同时/或者达到恰好一次的传递效果,应当看看更高层面的Trdent API,它同时也提供了微批处理的方式。
使用Storm的公司有:Twitter,雅虎,Spotify,腾讯还有The Weather Channel等。
l Spark
说到微批处理,如果你必须有状态的计算,恰好一次的递送,并且不介意高延迟的话,那么可以考虑Spark Streaming,特别如果你还计划图形操作、机器学习或者访问SQL的话,Apache Spark的stack允许你将一些library与数据流相结合(Spark SQL,Mllib,GraphX),它们会提供便捷的一体化编程模型。尤其是数据流算法(例如:K均值流媒体)允许Spark实时决策的促进。
使用Spark的公司有:亚马逊,雅虎,NASA JPL,eBay还有百度等。
l Samza
如果你有大量的状态需要处理,比如每个分区都有许多十亿位元组,那么可以选择Samza。由于Samza将存储与处理放在同一台机器上,在保持处理高效的同时,还不会额外载入内存。这种框架提供了灵活的可插拔API:它的默认execution、消息发送还有存储引擎操作都可以根据你的选择随时进行替换。此外,如果你有大量的数据流处理阶段,且分别来自不同代码库的不同团队,那么Samza的细颗粒工作特性会尤其适用,因为它们可以在影响最小化的前提下完成增加或移除的工作。
使用Samza的公司有:LinkedIn,Intuit,Metamarkets,Quantiply,Fortscale等。