Kafka:
优点: 吞吐量⾮常⼤,性能⾮常好,集群⾼可⽤。
缺点:会丢数据,功能⽐较单⼀。
使⽤场景:⽇志分析、⼤数据采集。
RabbitMQ:
优点: 消息可靠性⾼,功能全⾯。
缺点:吞吐量⽐较低,消息积累会严重影响性能。erlang语⾔不好定制。
使⽤场景:⼩规模场景。
RocketMQ:
优点:⾼吞吐、⾼性能、⾼可⽤,功能⾮常全⾯。
缺点:开源版功能不如云上商业版。官⽅⽂档和周边⽣态还不够成熟。客户端只⽀持java。
使⽤场景:⼏乎是全场景。
Kafka 是⼀种⾼吞吐量、分布式、基于发布/订阅的消息系统,最初由 LinkedIn 公司开发,使⽤Scala
语⾔编写,⽬前是 Apache 的开源项⽬。
**broker:**Kafka 服务器,负责消息存储和转发。
**topic:**消息类别, Kafka 按照 topic 来分类消息。
**partition:**topic 的分区,⼀个 topic 可以包含多个 partition,topic 消息保存在各个partition 上。
**offset:**消息在⽇志中的位置,可以理解是消息在 partition 上的偏移量,也是代表该消息的唯⼀序号。
**Producer:**消息⽣产者。
**Consumer:**消息消费者。
**Consumer Group:**消费者分组,每个 Consumer 必须属于⼀个 group。
**Zookeeper:**保存着集群 broker、 topic、 partition等 meta 数据;另外,还负责 broker 故障发现, partition leader 选举,负载均衡等功能。
Kafka的⽣产者采⽤的是异步发送消息机制,当发送⼀条消息时,消息并没有发送到Broker⽽是缓存起
来,然后直接向业务返回成功,当缓存的消息达到⼀定数量时再批量发送给Broker。这种做法减少了⽹
络io,从⽽提⾼了消息发送的吞吐量,但是如果消息⽣产者宕机,会导致消息丢失,业务出错,所以理
论上kafka利⽤此机制提⾼了性能却降低了可靠性。
我们都知道,kafka是依赖于文件系统来保存和缓冲消息的。在其他消息队列RabbitMQ中,使用的是内存作为默认的存储介质,而磁盘作为备选介质,以此来实现高吞吐和低延迟的效果;redis则是完全依赖于内存实现的。那为什么kafka采用这种持久化的形式还能提供如此有竞争力的性能呢?
1.kafka对写操作的优化
首先kafka在同一个topic partition中的数据是有序的 ,kafka设计的时候,就只支持在文件末尾进行追加,而不支持修改操作,属于典型的顺序写入操作,操作系统对顺序读写坐了深层次的优化----预读和后写(将一个大的磁盘块读入内存,将很多小逻辑的写操作在内存中完成后,一次性将这一块数据写入磁盘中)。有相关研究表明,对磁盘的顺序写入速度远远大于对磁盘的随机写入,甚至还快过了对内存的随机写入。
2.kafka对读操作的优化
kafka在读取的时候使用了零拷贝技术,降低对文件的拷贝次数,一定程度上提升了速度。
3.kafka大量使用了页缓存
前面对读写操作的优化,使得kafka能承载吞吐量也不容小视,但这并不是kafka在全局性能上具备竞争力的全部因素。接下来将介绍的是页缓存,kafka是如何借助操作系统的帮助提升性能的。
页缓存是操作系统对数据文件的读写提供的一种缓冲技术,目的是为了减少I/O操作的次数。
当进程读取某个文件的时候,操作系统会先查看待读取的数据所在的页是否在页缓存中,如果在则直接返回给进程,如果不在则从磁盘读取后先写入页缓存,然后再将数据返回给进程。
当进程写入某个文件的时候,操作系统也会查看需要操作的页是否在页缓存中,如果存在则进行写入,如果不在则从磁盘中读取后再进行相关写入操作,被修改后的页,操作系统会在合适的时间内刷入磁盘来保证数据的一致性。
kafka大量使用页缓存,这也是kafka实现高性能的原因之一。 对于一个进程来说,他会在进程内部缓存所需要的数据,然而这些数据很有可能也缓存在操作系统的页缓存中,也就是这一部分数据被缓存了两次。就算kafka服务重启,页缓存内的数据也还是存在,但进程内的数据则需要重新加载。这也在一定程度上能简化代码,而且维护页缓存和文件的一致性问题交给操作系统完成会比进程内维护要更加的安全、高效。
虽然kafka的消息加载到页缓存中后,由操作系统择机刷入磁盘,但是kafka也还是提供了同步刷盘和间断性强制刷盘的功能,这些功能可以通过控制参数来实现。同步刷盘确实可以实现数据的可靠性,但是并不建议这样做,提高消息的可靠性应该由副本机制来实现,而不是由严重损耗性能的同步刷盘来实现。
特性 | ActiveMq | RabbitMq | RocketMQ | Kafka |
---|---|---|---|---|
成熟度 | 成熟 | 成熟 | 比较成熟 | 成熟的日志领域 |
时效性 | 微秒级 | 毫秒级 | 毫秒级 | |
社区活跃度 | 低 | 高 | 高 | 高 |
单机吞吐量 | 万级,吞吐量比RocketMQ和Kafka要低了一个数量级 | 万级,吞吐量比RocketMQ和Kafka要低了一个数量级 | 10万级,RocketMQ也是可以支撑高吞吐的一种MQ | 10万级别,这是kafka最大的优点,就是吞吐量高。一般配合大数据类的系统来进行实时数据计算、日志采集等场景 |
topic数量对吞吐量的影响 | topic可以达到几百,几千个的级别,吞吐量会有较小幅度的下降这是RocketMQ的一大优势,在同等机器下,可以支撑大量的topic | topic从几十个到几百个的时候,吞吐量会大幅度下降所以在同等机器下,kafka尽量保证topic数量不要过多。如果要支撑大规模topic,需要增加更多的机器资源 | ||
可用性 | 高,基于主从架构实现高可用性 | 高,基于主从架构实现高可用性 | 非常高,分布式架构 | 非常高,kafka是分布式的,一个数据多个副本,少数机器宕机,不会丢失数据,不会导致不可用 |
消息可靠性 | 有较低的概率丢失数据 | 经过参数优化配置,可以做到0丢失 | 经过参数优化配置,消息可以做到0丢失 | |
功能支持 | MQ领域的功能极其完备 | 基于erlang开发,所以并发能力很强,性能极其好,延时很低 | MQ功能较为完善,还是分布式的,扩展性好 | 功能较为简单,主要支持简单的MQ功能,在大数据领域的实时计算以及日志采集被大规模使用,是事实上的标准 |
优劣势总结 | 非常成熟,功能强大,在业内大量的公司以及项目中都有应用偶尔会有较低概率丢失消息而且现在社区以及国内应用都越来越少,官方社区现维护越来越少,几个月才发布一个版本而且确实主要是基于解耦和异步来用的,较少在大规模吞吐的场景中使用 | rlang语言开发,性能极其好,延时很低;吞吐量到万级,MQ功能比较完备而且开源提供的管理界面非常棒,用起来很好用社区相对比较活跃,几乎每个月都发布几个版本分在国内一些互联网公司近几年用rabbitmq也比较多一些但是问题也是显而易见的,RabbitMQ确实吞吐量会低一些,这是因为他做的实现机制比较重。而且erlang开发,国内有几个公司有实力做erlang源码级别的研究和定制?如果说你没这个实力的话,确实偶尔会有一些问题,你很难去看懂源码,你公司对这个东西的掌控很弱,基本职能依赖于开源社区的快速维护和修复bug。而且rabbitmq集群动态扩展会很麻烦,不过这个我觉得还好。其实主要是erlang语言本身带来的问题。很难读源码,很难定制和掌控。 | 接口简单易用,而且毕竟在阿里大规模应用过,有阿里品牌保障日处理消息上百亿之多,可以做到大规模吞吐,性能也非常好,分布式扩展也很方便,社区维护还可以,可靠性和可用性都是ok的,还可以支撑大规模的topic数量,支持复杂MQ业务场景而且一个很大的优势在于,阿里出品都是java系的,我们可以自己阅读源码,定制自己公司的MQ,可以掌控社区活跃度相对较为一般,不过也还可以,文档相对来说简单一些,然后接口这块不是按照标准JMS规范走的有些系统要迁移需要修改大量代码还有就是阿里出台的技术,你得做好这个技术万一被抛弃,社区黄掉的风险,那如果你们公司有技术实力我觉得用RocketMQ挺好的 | kafka的特点其实很明显,就是仅仅提供较少的核心功能,但是提供超高的吞吐量,ms级的延迟,极高的可用性以及可靠性,而且分布式可以任意扩展同时kafka最好是支撑较少的topic数量即可,保证其超高吞吐量而且kafka唯一的一点劣势是有可能消息重复消费,那么对数据准确性会造成极其轻微的影响,在大数据领域中以及日志采集中,这点轻微影响可以忽略这个特性天然适合大数据实时计算以及日志收集 |
一般的业务系统要引入MQ,最早大家都用ActiveMQ,但是现在确实大家用的不多了,没经过大规模吞吐量场景的验证,社区也不是很活跃;
后来大家开始用RabbitMQ,但是确实erlang语言阻止了大量的java工程师去深入研究和掌控他,对公司而言,几乎处于不可控的状态,但是确实人是开源的,比较稳定的支持,活跃度也高;
不过现在确实越来越多的公司,会去用RocketMQ,确实很不错,但是我提醒一下自己想好社区万一突然黄掉的风险,对自己公司技术实力有绝对自信的,我推荐用RocketMQ,否则回去老老实实用RabbitMQ吧,人是活跃开源社区,绝对不会黄
所以中小型公司,技术实力较为一般,技术挑战不是特别高,用RabbitMQ是不错的选择;大型公司,基础架构研发实力较强,用RocketMQ是很好的选择
如果是大数据领域的实时计算、日志采集等场景,用Kafka是业内标准的,绝对没问题,社区活跃度很高,绝对不会黄,何况几乎是全世界这个领域的事实性规范
开发中,该选择哪种消息中间件,下面给出几点小建议:
1、ActiveMQ已经不推荐使用了,因为社区活跃度很低,没什么人再去维护了。一旦使用过程中出现了问题,比较难以找到解决办法;
2、RabbitMQ现在是使用的比较多的,吞吐量也达到了万级,而且延时低,最好的一个优点就是它提供了一个后台管理系统,对于中小型公司来说很有用的;同时目前来看,社区活跃度也比较高。缺点就是开发语言使用的是erlang语言,对于Java开发者来说,erlang语言比较难以看懂,不能去深入的研究,只能简单的使用。
3、RocketMQ的阿里开源的,现在社区也比较活跃,并且是用Java语言开发的,支持分布式集群。但是有被弃用的风险,一旦阿里什么时候不维护了,那么就有可能被废弃掉。如果是有能力大公司还好,可以自己去钻研源码,自己维护,如果是小公司的话,那么就被坑了。
4、Kafka主要用在大数据领域。它的主要优点就是吞吐量大,同时也是分布式的。
淘宝内部的交易系统使用了淘宝自主研发的Notify消息中间件,使用MySQL作为消息存储媒介,支持水平扩容。为了进一步降低成本,阿里中间件团队认为Notify可进一步优化。
2011年初,Linkedin开源了kafka, 阿里中间件团队在对kafka做了充分的review之后,被kafka的无限消息堆积能力、高效的持久化速度深深吸引,但同时发现kafka主要定位于日志传输,对于使用在淘宝交易、订单、充值等场景下,还有若干特性不满足。因此,阿里中间件团队基于Java重新编写了RocketMQ,定位于不仅限于日志场景的可靠消息传输。
目前,RocketMQ在阿里集团被广泛应用于订单、充值、交易、流计算、消息推送、日志流式处理、binlog分发等场景。
RocketMQ:支持异步实时刷盘、同步刷盘、同步复制、异步复制。
kafka:使用异步刷盘方式,异步复制/同步复制。
总结:
1、RocketMQ支持kafka所不具备的“同步刷盘”功能,在单机可靠性上比kafka更高,不会因为操作系统Crash而导致数据丢失。
2、kafka的同步replication理论上性能低于RocketMQ的replication,这是因为kafka的数据以partition为单位,这样一个kafka实例上可能多上百个partition。而一个RocketMQ实例上只有一个partition,RocketMQ可以充分利用IO组的commit机制,批量传输数据。同步replication与异步replication相比,同步replication性能上损耗约20%-30%。
一句话概括:RocketMQ新增了同步刷盘机制,保证了可靠性;一个RocketMQ实例只有一个partition, 在replication时性能更好。
1、kafka单机写入TPS月在百万条/秒,消息大小为10个字节。
2、RocketMQ单机写入TPS单实例约7万条/秒,若单机部署3个broker,可以跑到最高12万条/秒,消息大小为10个字节。
总结:
kafka的单机TPS能跑到每秒上百万,是因为Producer端将多个小消息合并,批量发向broker。
那么RocketMQ为什么没有这样做呢?
一句话概括:RocketMQ写入性能上不如kafka, 主要因为kafka主要应用于日志场景,而RocketMQ应用于业务场景,为了保证消息必达牺牲了性能,且基于线上真实场景没有在RocketMQ层做消息合并,推荐在业务层自己做。
1、kafka单机若超过了64个partition/队列,CPU load会发生明显飙高,partition越多,CPU load越高,发消息的响应时间变长。
2、RocketMQ单机支持最高5万个队列,CPU load不会发生明显变化。
队列多有什么好处呢?
1、单机可以创建更多个topic, 因为每个topic都是有一组队列组成。
2、消费者的集群规模和队列数成正比,队列越多,消费类集群可以越大。
一句话概括:RocketMQ支持的队列数远高于kafka支持的partition数,这样RocketMQ可以支持更多的consumer集群。
1、kafka采用短轮询的方式,实时性取决于轮询时间间隔,0.8以后版本支持长轮询。
2、RocketMQ使用长轮询,同Push实时性一致,消息投递的延迟通常在几毫秒内,
一句话:kafka与RocketMQ都支持长轮询,消息投递的延迟在几毫秒内。
1、kafka不支持消费失败重试。
2、RocketMQ消费失败支持定时重试,每次重试间隔时间顺延。
总结:以充值类应用为例,若当前时刻调用运营商网管失败,可能运营商网关此时压力过大,稍后再调用就会成功。这里的重试指可靠的重试,即失败重试的消息不是因为consumer宕机而导致的消息丢失。
一句话概括:RocketMQ支持消费失败重试功能,主要用于第一次调用不成功,后面可调用成功的场景。而kafka不支持消费失败重试。
1、kafka可保证同一个partition上的消息有序,但一旦broker宕机,就会产生消息乱序。
2、Rocket支持严格的消息顺序,一台broker宕机,发送消息会失败,但不会乱序。举例:MySQL的二进制日志分发需要保证严格的顺序。
一句话概括:kafka不保证消息有序,RocketMQ可保证严格的消息顺序,即使单台Broker宕机,仅会造成消息发送失败,但不会消息乱序。
1、kafka不支持定时消息
2、开源版本的RocketMQ仅支持定时级别,定时级别用户可定制
1、kafka不支持分布式事务消息
2、RocketMQ支持分布式事务消息。
1、kafka不支持消息查询
2、RocketMQ支持根据消息标识(发送消息时指定一个消息key, 任意字符串,如指定为订单编号)查询消息,也支持根据消息内容查询消息。
总结:消息查询功能对于定位消息丢失问题非常有用,例如某个订单处理失败,可用此功能查询是消息没收到,还是收到了但处理出错了。
一句话概括:RocketMQ支持按消息标识或消息内容查询消息,用于排查消息丢失问题;kafka不支持消息查询。
1、kafka可按照消息的offset来回溯消息
2、RocketMQ支持按照时间来回溯消息,精度到毫秒,例如从一天的几点几分几秒几毫秒来重新消费消息。
总结:RocketMQ按时间做回溯消息的典型应用场景为,consumer做订单分析,但是由于程序逻辑或依赖的系统发生故障等原因,导致今天处理
的消息全部无效,需要从昨天的零点重新处理。
1、kafka的消息并行度,依赖于topic里配置的partition数,如果partition数为10,那么最多10台机器来消费,每台机器只能开启一个线程;或者一台机器消费,最多开启10个线程。消费的并行度与partition个数一致。
2、RocketMQ并行消费分两种情况:
1)顺序消费方式的并行度与kafka一致。
2)乱序消费方式的并行度取决于consumer的线程数,如topic配置10个队列,10台机器消费,每台机器100个线程,那么并行度为1000。
一句话概括:kafka的消费并行度等于partition数;RocketMQ的消费并行度等于消费的线程数,不受队列数限制。
1、kafka采用scala开发
2、RocketMQ采用Java开发
kafka比RocketMQ的消息堆积能力更强,不过RocketMQ单机也可支持亿级的消息积压能力,这个堆积能力也能够完全满足业务需求。
1、kafka社区更新较慢
2、RocketMQ的Github社区有250人,公司用户登记了联系方式,QQ群超过1000人,
3、kafka原开发团队成立了新公司,暂时未看到相关产品。
4、RocketMQ已在阿里云商业化,目前以云服务形式供外部商用,并向用户承诺99.99%的可靠性,同时彻底解决了用户自己搭建MQ产品的运维复杂性问题。
1、kafka在日志领域比较成熟
2、RocketMQ在阿里集团内部有大量的应用在使用,并顺利支持了多次天猫双十一的考验。
kafka和RocketMQ的总体区别是,kafka设计初衷是用于日志传输,而RocketMQ的设计用于解决各类应用可靠的消息传输,阿里云官网承诺RocketMQ数据可靠性为10个9,服务可靠性为99.95%。
1、单机吞吐量TPS可上百万,远高于RocketMQ的TPS7万每秒,适用于日志类消息。
2、kafka支持多语言的客户端
**1、保证消息不丢( 数据可靠性达10个9)
2、可严格保证消息有序
3、支持分布式事务消息
4、支持按时间做消息回溯(可精确到毫秒级)
5、支持按标识和内容查询消息,用于排查丢消息
6、支持消费失败重试
7、可支持更多的partition, 即更多的消费线程数
在分布式系统中,我们广泛运用消息中间件进行系统间的数据交换,便于异步解耦。现在开源的消息中间件有很多,前段时间产品 RocketMQ (MetaQ的内核) 也顺利开源,得到大家的关注。
MQ简介
MQ,Message queue,消息队列,就是指保存消息的一个容器。具体的定义这里就不类似于数据库、缓存等,用来保存数据的。当然,与数据库、缓存等产品比较,也有自己一些特点,具体的特点后文会做详细的介绍。
现在常用的MQ组件有ActiveMQ、RabbitMQ、RocketMQ、ZeroMQ、MetaMQ,当然近年来火热的kafka,从某些场景来说,也是MQ,当然kafka的功能更加强大,虽然不同的MQ都有自己的特点和优势,但是,不管是哪种MQ,都有MQ本身自带的一些特点,下面,介绍MQ的特点。
1、先进先出
不能先进先出,都不能说是队列了。消息队列的顺序在入队的时候就基本已经确定了,一般是不需人工干预的。而且,最重要的是,数据是只有一条数据在使用中。 这也是MQ在诸多场景被使用的原因。
2、发布订阅
发布订阅是一种很高效的处理方式,如果不发生阻塞,基本可以当做是同步操作。这种处理方式能非常有效的提升服务器利用率,这样的应用场景非常广泛。
3、持久化
持久化确保MQ的使用不只是一个部分场景的辅助工具,而是让MQ能像数据库一样存储核心的数据。
4、分布式
在现在大流量、大数据的使用场景下,只支持单体应用的服务器软件基本是无法使用的,支持分布式的部署,才能被广泛使用。而且,MQ的定位就是一个高性能的中间件。
应用场景
那么,消息中间件性能究竟哪家强?
带着这个疑问,我们中间件测试组对常见的三类消息产品(Kafka、RabbitMQ、RocketMQ)做了性能比较。
Kafka是LinkedIn开源的分布式发布-订阅消息系统,目前归属于Apache顶级项目。Kafka主要特点是基于Pull的模式来处理消息消费,追求高吞吐量,一开始的目的就是用于日志收集和传输。0.8版本开始支持复制,不支持事务,对消息的重复、丢失、错误没有严格要求,适合产生大量数据的互联网服务的数据收集业务。
RabbitMQ是使用Erlang语言开发的开源消息队列系统,基于AMQP协议来实现。AMQP的主要特征是面向消息、队列、路由(包括点对点和发布/订阅)、可靠性、安全。AMQP协议更多用在企业系统内,对数据一致性、稳定性和可靠性要求很高的场景,对性能和吞吐量的要求还在其次。
RocketMQ是阿里开源的消息中间件,它是纯Java开发,具有高吞吐量、高可用性、适合大规模分布式系统应用的特点。RocketMQ思路起源于Kafka,但并不是Kafka的一个Copy,它对消息的可靠传输及事务性做了优化,目前在阿里集团被广泛应用于交易、充值、流计算、消息推送、日志流式处理、binglog分发等场景。
对比Kafka、RabbitMQ、RocketMQ发送小消息(124字节)的性能。这次压测我们只关注服务端的性能指标,所以压测的标准是:
不断增加发送端的压力,直到系统吞吐量不再上升,而响应时间拉长。这时服务端已出现性能瓶颈,可以获得相应的系统最佳吞吐量。
在同步发送场景中,三个消息中间件的表现区分明显:
Kafka的吞吐量高达17.3w/s,不愧是高吞吐量消息中间件的行业老大。这主要取决于它的队列模式保证了写磁盘的过程是线性IO。此时broker磁盘IO已达瓶颈。
RocketMQ也表现不俗,吞吐量在11.6w/s,磁盘IO %util已接近100%。RocketMQ的消息写入内存后即返回ack,由单独的线程专门做刷盘的操作,所有的消息均是顺序写文件。
RabbitMQ的吞吐量5.95w/s,CPU资源消耗较高。它支持AMQP协议,实现非常重量级,为了保证消息的可靠性在吞吐量上做了取舍。我们还做了RabbitMQ在消息持久化场景下的性能测试,吞吐量在2.6w/s左右。
在服务端处理同步发送的性能上,Kafka>RocketMQ>RabbitMQ。
附录:
测试环境
服务端为单机部署,机器配置如下:
应用版本:
测试脚本
前面我们对比了最简单的小消息发送场景,Kafka暂时胜出。但是,作为经受过历次双十一洗礼的RocketMQ,在互联网应用场景中更有它优越的一面。
是使用Erlang编写的一个开源的消息队列,本身支持很多的协议:AMQP,XMPP, SMTP, STOMP,也正是如此,使的它变的非常重量级,更适合于企业级的开发。同时实现了一个经纪人(Broker)构架,这意味着消息在发送给客户端时先在中心队列排队。对路由(Routing),负载均衡(Load balance)或者数据持久化都有很好的支持。
是一个Key-Value的NoSQL数据库,开发维护很活跃,虽然它是一个Key-Value数据库存储系统,但它本身支持MQ功能,所以完全可以当做一个轻量级的队列服务来使用。对于RabbitMQ和Redis的入队和出队操作,各执行100万次,每10万次记录一次执行时间。测试数据分为128Bytes、512Bytes、1K和10K四个不同大小的数据。实验表明:入队时,当数据比较小时Redis的性能要高于RabbitMQ,而如果数据大小超过了10K,Redis则慢的无法忍受;出队时,无论数据大小,Redis都表现出非常好的性能,而RabbitMQ的出队性能则远低于Redis。
号称最快的消息队列系统,尤其针对大吞吐量的需求场景。ZMQ能够实现RabbitMQ不擅长的高级/复杂的队列,但是开发人员需要自己组合多种技术框架,技术上的复杂度是对这MQ能够应用成功的挑战。ZeroMQ具有一个独特的非中间件的模式,你不需要安装和运行一个消息服务器或中间件,因为你的应用程序将扮演了这个服务角色。你只需要简单的引用ZeroMQ程序库,可以使用NuGet安装,然后你就可以愉快的在应用程序之间发送消息了。但是ZeroMQ仅提供非持久性的队列,也就是说如果down机,数据将会丢失。其中,Twitter的Storm中使用ZeroMQ作为数据流的传输。
Apache ActiveMQ 是最受欢迎且功能最强大的开源消息传递和Integration Patterns服务器。
Apache ActiveMQ速度快,支持许多跨语言客户端和协议,带有易于使用的企业集成模式和许多高级功能,同时完全支持JMS 1.1和J2EE 1.4。Apache ActiveMQ是在Apache 2.0许可下发布
特征
支持Java消息服务(JMS) 1.1 版本
Spring Framework
集群 (Clustering)
支持的编程语言包括:C、C++、C#、Delphi、Erlang、Adobe Flash、Haskell、Java、JavaScript、Perl、PHP、Pike、Python和Ruby
协议支持包括:OpenWire、REST、STOMP、WS-Notification、MQTT、XMPP以及AMQP [1]
Kafka是Apache下的一个子项目,是一个高性能跨语言分布式Publish/Subscribe消息队列系统,而Jafka是在Kafka之上孵化而来的,即Kafka的一个升级版。具有以下特性:快速持久化,可以在O(1)的系统开销下进行消息持久化;高吞吐,在一台普通的服务器上既可以达到10W/s的吞吐速率;完全的分布式系统,Broker、Producer、Consumer都原生自动支持分布式,自动实现复杂均衡;支持Hadoop数据并行加载,对于像Hadoop的一样的日志数据和离线分析系统,但又要求实时处理的限制,这是一个可行的解决方案。Kafka通过Hadoop的并行加载机制来统一了在线和离线的消息处理,这一点也是本课题所研究系统所看重的。Apache Kafka相对于ActiveMQ是一个非常轻量级的消息系统,除了性能非常好之外,还是一个工作良好的分布式系统。
Kafka和RabbitMq一样是通用意图消息代理,他们都是以分布式部署为目的。但是他们对消息语义模型的定义的假设是非常不同的。我对"AMQP 更成熟"这个论点是持怀疑态度的。让我们用事实说话来看看用什么解决方案来解决你的问题。
a) 以下场景你比较适合使用Kafka。你有大量的事件(10万以上/秒)、你需要以分区的,顺序的,至少传递成功一次到混杂了在线和打包消费的消费者、你希望能重读消息、你能接受目前是有限的节点级别高可用或则说你并不介意通过论坛/IRC工具得到还在幼儿阶段的软件的支持。
b) 以下场景你比较适合使用RabbitMQ。你有较少的事件(2万以上/秒)并且需要通过复杂的路由逻辑去找到消费者、你希望消息传递是可靠的、你并不关心消息传递的顺序、你需要现在就支持集群-节点级别的高可用或则说你需要7*24小时的付费支持(当然也可以通过论坛/IRC工具)。
redis 消息推送(基于分布式 pub/sub)多用于实时性较高的消息推送,并不保证可靠。其他的mq和kafka保证可靠但有一些延迟(非实时系统没有保证延迟)。redis-pub/sub断电就清空,而使用redis-list作为消息推送虽然有持久化,但是又太弱智,也并非完全可靠不会丢。另外一点,redis 发布订阅除了表示不同的 topic 外,并不支持分组,比如kafka中发布一个东西,多个订阅者可以分组,同一个组里只有一个订阅者会收到该消息,这样可以用作负载均衡。比如,kafka 中发布:topic = “发布帖子” data=“文章1” 这个消息,后面有一百台服务器每台服务器都是一个订阅者,都订阅了这个 topic,但是他们可能分为三组,A组50台,用来真的做发布文章,A组50台里所有 subscriber 都订阅了这个topic。由于在同一组,这条消息 (topic=“发布帖子”, data=“文章1”)只会被A组里面一台当前空闲的机器收到。而B组25台服务器用于统计,C组25台服务器用于存档备份,每组只有一台会收到。用不同的组来决定每条消息要抄送出多少分去,用同组内哪些订阅者忙,哪些订阅者空闲来决定消息会被分到哪台服务器去处理,生产者消费者模型嘛。redis完全没有这类机制,这两点是最大的区别。
redis作者做内存数据库基础上增加了消息pub/sub。mq一般都采用订阅~发布模型,如果你考虑性能,主要关注点就放在消费模型是pull还是push。影响最大的,应该是存储结构。kafka的性能要在topic数量小于64的时候,才能发挥威力。partition决定的。极限情况下丢消息,例如:主写入消息后,主机器宕机,并硬盘损坏。review代码的时候发现的。rabbit不知道,但是rocket的性能是(万条每秒),并且能够横向无限扩展,单机topic数量在256时,性能损失较小。rocket可以说是kafka的变种,是阿里在充分reviewkafka代码后,开发的metaQ。在不断更新,修补以后,阿里把metaQ3.0更名为rocket,并且rocket是java写的易于维护。另外就是rocket和kafka有类似无限堆积的能力。想想,断电不丢消息,积压两亿条消息毫无压力,niubility kafka和rocket mq性能根本不需要考虑的问题。
RabbitMQ遵循AMQP协议,由内在高并发的erlanng语言开发,用在实时的对可靠性要求比较高的消息传递上,适合企业级的消息发送订阅,也是比较受到大家欢迎的。
kafka是Linkedin于2010年12月份开源的消息发布订阅系统,它主要用于处理活跃的流式数据,大数据量的数据处理上。常用日志采集,数据采集上。
RabbitMQ遵循AMQP协议,RabbitMQ的broker由Exchange,Binding,queue组成,其中exchange和binding组成了消息的路由键;客户端Producer通过连接channel和server进行通信,Consumer从queue获取消息进行消费(长连接,queue有消息会推送到consumer端,consumer循环从输入流读取数据)。rabbitMQ以broker为中心;有消息的确认机制。
kafka遵从一般的MQ结构,producer,broker,consumer,以consumer为中心,消息的消费信息保存的客户端consumer上,consumer根据消费的点,从broker上批量pull数据;无消息确认机制。
kafka具有高的吞吐量,内部采用消息的批量处理,zero-copy机制,数据的存储和获取是本地磁盘顺序批量操作,具有O(1)的复杂度,消息处理的效率很高。
rabbitMQ在吞吐量方面稍逊于kafka,他们的出发点不一样,rabbitMQ支持对消息的可靠的传递,支持事务,不支持批量的操作;基于存储的可靠性的要求存储可以采用内存或者硬盘。
rabbitMQ支持miror的queue,主queue失效,miror queue接管。
kafka的broker支持主备模式。
kafka采用zookeeper对集群中的broker、consumer进行管理,可以注册topic到zookeeper上;通过zookeeper的协调机制,producer保存对应topic的broker信息,可以随机或者轮询发送到broker上;并且producer可以基于语义指定分片,消息发送到broker的某分片上。
rabbitMQ的负载均衡需要单独的loadbalancer进行支持。
Kafka是可靠的分布式日志存储服务。用简单的话来说,你可以把Kafka当作可顺序写入的一大卷磁带, 可以随时倒带,快进到某个时间点重放。先说下日志的定义:日志是数据库的核心,是对数据库的所有变更的严格有序记录,“表”是变更的结果。日志的其他名字有: Changelog, Write Ahead Log, Commit Log, Redo Log, Journaling.Kafka的特征如下:高写入速度:Kafka能以超过1Gbps NIC的速度写这盘磁带(实际可以到SATA 3速度,参考Benchmarking Apache Kafka: 2 Million Writes Per Second (On Three Cheap Machines)),充分利用了磁盘的物理特性,即,随机写入慢(磁头冲停),顺序写入快(磁头悬浮)。高可靠性: 通过zookeeper做分布式一致性,同步到任意多块磁盘上,故障自动切换选主,自愈。高容量:通过横向扩展,LinkedIn每日通过Kafka存储的新增数据高达175TB,8000亿条消息,可无限扩容,类似把两条磁带粘到一起。传统业务数据库的根本缺陷在于:1. 太慢,读写太昂贵,无法避免的随机寻址。(磁盘最快5ms寻址,固态又太昂贵。)2. 根本无法适应持续产生的数据流,越用越慢。(索引效率问题)3. 无法水平scale。(多半是读写分离,一主多备。另: NewSQL通过一致性算法,有多主。)针对这些问题,Kafka提出了一种方法: “log-centric approach(以日志为中心的方法)。”将传统数据库分为两个独立的系统,即日志系统和索引系统。“持久化和索引分开,日志尽可能快的落地,索引按照自己的速度追赶。”在数据可靠性在得到Kafka这种快速的,类似磁带顺序记录方式保障的大前提下。数据的呈现,使用方式变得非常灵活,可以根据需要将数据流同时送入搜索系统,RDBMS系统,数据仓库系统, 图数据库系统,日志分析等这些各种不同的数据库系统。 这些不同的系统只不过是一种对Kafka磁带数据的一种诠释,一个侧面,一个索引,一个快照。数据丢了,没关系,重放一遍磁带即可,更多的时候,对这些各式数据库系统的维护只是需要定期做一个快照,并拷贝到一个安全的对象存储(如S3) 而已。 一句话:“日志都是相同的日志,索引各有各的不同。”关于流计算:在以流为基本抽象的存储模型下,数据流和数据流之间,可以多流混合处理,或者流和状态,状态和状态的JOIN处理,这就是Kafka Stream提供的功能。 一个简单的例子是,在用户触发了某个事件后,和用户表混合处理,产生数据增补(Augment),再进入数据仓库进行相关性分析,一些简单的窗口统计和实时分析也很容易就能满足,比如 在收到用户登录消息的时候,在线人数+1, 离线的时候-1,反应出当前系统的在线用户总数。