文章目录
- rabbitMQ和kafka
- kafka和rocketMQ
- rabbitMq和rocketMQ
- MQ选型
- 消息队列常使用的注意事项
- 如何保证系统的高可用
- 如何保证消息不会丢失
- rabbitmq
- rocketMq
rabbitMQ和kafka
- 语言
kafka使用scala写的,rabbitmq使用erlang写的,rocketMQ使用java写的 - 消费模型
RabbitMQ中pull和push都有实现,kafka和rocketMQ中只有pull - 架构组成
rabbtmq是基于AMQP协议开发,broker由exchange、binding、queue组成
kafka采用mq结构,broker有分区的概念。所以可以更好的伸缩性,支持横向扩展。 - 吞吐量
kafka具有更高的吞吐量,内部采用消息的批量处理机制,使用的零拷贝机制,消息处理效率高。 - 集群
kafka的集群可以通过zk来管理。rabbitmq要通过第三方的haproxy和keeplive来实现 - 延迟队列
rabbitmq支持延迟消息,kafka不支持。 - 路由分发
路由的分发上,rabbit有通配符更加灵活。
消息的留存上,kafka消费完了消息会保留,rabbitmq消费完了就回删除。kafka可以设置retention,清理消息。 - Kafka功能比较的单一, 主要的就是支持收发消息,没有延迟消息实现
- 选择上
选择rabbitMQ情况,高级灵活的路由规则,需要延迟队列的支持。更简单的消费者实现。高级容错能力,保证消息不丢失,消费消息可以手动返回basicACK,保证消息正确消费。
选择kafka情况:严格的消息顺序(同一个partition的消息时有序的),延长消息的留存时间,需要高伸缩的能力。
kafka和rocketMQ
- 消息保存
rocketmq每个broker的消息是统一存储在一个commitlog文件中,kafka是每个分区partition保存一定量的消息。 - 注册中心
kafka可以用使用zk统一管理broker,rocketmq使用的是一个namesever.
- 引申 nameserver工作原理? 每个节点启动会遍历namesever,注册自己的信息,每个30秒发送心跳到到nameserver,nameserver每隔10秒检查一下,各个broker的心跳发送时间,超过120没有心跳,就认为挂掉,从路由消息里面移除
- rockemq引申为什么不用zk呢? rocketmq早期也用了zk,后面为了去掉zk依赖,采用了自己的nameserver,使服务更加轻量级,也减少了维护成本。
- 主从同步机制
kafka的消息同步是follower 向master发起 fetch 请求,leader 收到请求以后,将数据返回给follower,同时更新同步的位置,达到消息同步
rocketmq主从同步是,slave向master发送当前commitlog文件中的最大偏移量,master开始准备还未同步的数据,返回给slave,slave将数据同步,同时更新最大偏移量。 - 刷盘持久化
rocketMQ支持同步刷盘,每次消息写入都同步刷盘,保证数据可靠性,但是影响吞吐量。一般采用异步刷盘,同步双写。同步双写是指,消息同时写入master和slave的缓存中,才返回客户端成功,接着再异步刷盘持久化 ,可以保证数据不丢失(不然master故障后,有可能造成数据丢失)。
kafka都是异步刷盘。返回的ack有三种,0-生产者不等待broker的ack,继续发送消息 1- 等待leader落盘返回 -1-主从全部落盘才返回ack - 吞吐量
kafka的吞吐量更大 - 延迟消息
rocketmq支持延迟消息。 - 消费消息
rocketMQ查询更加灵活,除了queue的offset外,还可以指定key,查询适配的消息 - 消费实时性
kafka是通过轮询拉取消息,实时性取决轮询间隔。
rocketmq是通过长连接方式,当有新消息时候,就立即拉取,实时性比较高。
rabbitMq和rocketMQ
- rabbitMQ吞吐量很低,一秒只有几万的样子,横向扩展比较麻烦。采用erlang语言开发,不便于查找问题和维护。如果流量比较平稳,没有特别高的并发量,选择rabbitMQ足够。
- rocketMQ吞吐量更高,采用了类似分片思想message queue,支持容量的横向扩展。如果公司发展迅猛,流量爆发式增加,又想使用一些高级功能,比如延迟消息,可以使用rocketMQ。
- rabbitMQ和rocketMQ都可以保证消息不丢失
rabbitMQ通过开启手动ACK、发送者确认模式保证消息不丢失。
rocketMQ通过开启同步双写、同步刷盘的形式实现消息不丢失,但是同步刷盘性能较低。一般是采用的同步双写,异步刷盘(异步刷盘可能在broker宕机情况下,消息丢失)
MQ选型
- 如果我们业务只是做一些收发消息的单一需求,允许丢失消息的可能,但是又要求极高的吞吐量和高性能的话,就采用kafka,就比如日志收集,数据监控
- 如果公司业务平稳,没有巨大的并发量,也没有改源码的需求,可以选择用rabbitMQ
- 如果公司发展迅猛,经常搞一些秒杀活动,可以直接一步到位使用RocketMQ。
参考
消息队列常使用的注意事项
如何保证系统的高可用
- 就rabbitMq而言,有镜像模式概念,就是用户在发送数据时候,发送到mq机器上,并且持久化磁盘,然后通过设置镜像的queue,把数的持久化地址对应表同步到另外mq机器上。这种就有效防止一台mq挂了以后,另外的mq可以直接对外提供消费功能。
- 就rocketMq而言,分为多主集群结构,多主多备异步复制结构,多主多备同步复制结构。
如何保证消息不会丢失
rabbitmq
- 就rabbitmq而言,从生产者,消费者,消息队列角度分析。生产者而言,发送消息如果失败,则定义重试次数,一般设置成五次。两种解决方式1.通过设置事务模式,进行事务回滚重试。2.通过发送者异步确认确认模式开启。
就mq本身而言,需要做队列的持久化到磁盘的操作 - 对于exchange,还可以发送到备份交换机,或者将失败消息返回给生产者
- 开启消费者手动确认模式,保证成功消费了,再删除消息
- 总结就是一句话:发送者确认模式开启,消息持久化默认开启,消费者消费开启手动ack
rocketMq
- rocketMq而言,就是开始同步双写(master和slave同时写入缓存成功然后返回ack),异步刷盘(极端情况服务器突然宕机的情况,会丢失数据。如果要保证消息绝对不丢失,就开启同步刷盘,但是吞吐量会降低)
- 消费阶段,消费成功返回ConsumeConcurrentlyStatus.CONSUME_SUCCESS 状态给 Broker。没有返回的就可以继续消费。
- 这里要注意实现消息的幂等性,可以给消息定义唯一键,防止消息重复