MQ
用处
一、异步。可提高性能和吞吐量
二、解耦
三、削峰
四、可靠。常用消息队列可以保证消息不丢失、不重复消费、消息顺序、消息幂等
选型
一Kafak:吞吐量最大,性能最好,集群高可用。缺点:会丢数据,功能较单一。
二RabbitMQ:可靠性高,功能全面。缺点:吞吐量低,可能消息积累影响性能。
三RocketMQ:高吞吐、高性能、高可用、事务性消息。缺点:生态相对不成熟。
如何保证消息不丢失
可能会丢失消息的环节
生产者->MQ MQ主从复制 MQ存磁盘 MQ->消费者
依次解决
一、生产者发送消息到MQ:
Kafak:回调。RocketMQ:回调、事务性消息。RobbitMQ:回调、手动事务、事务性消息(不细腻)
回调:生产者发送消息之后会注册一个回调函数,MQ收到消息返回ack,表示已收到。
二、消息同步不丢失:
RocketMQ:
普通集群中,异步同步性能高,可能丢消息。同步同步相反。
同步同步是指master结点拿到消息后从节点发送消息,从节点存盘后返回生产者ack。
异步同步是指master结点收到消息后往从节点同步消息,并直接返回生产者ask。
Dledger集群-两阶段提交。类似于ZAB协议同步数据。
RabbitMQ:
普通集群中,消息分散存储,结点不主动进行消息同步,可能丢消息。
镜像集群中,会在集群之间主动进行消息同步,安全性较高。
Kafak:
通常用在允许消息少量丢失的场景。
三、MQ消息内存到磁盘消息不丢失:
RocketMQ:使用同步刷盘安全性高,性能低。异步刷盘相反。
broker收到消息后,消息在内存中,需要其他线程将消息刷新到磁盘。
RabbitMQ:将消息配置为持久化队列,新增的Quorum类型的队列,用Raft协议进行消息同步。
四、MQ消费者消费消息不丢失:
分析:消息队列中有消息的偏移量,一般是在本地事务执行完成后移动。异步可能会丢失消息
RocketMQ:使用默认方式消费即可,不要采用异步的方式。
RabbitMQ:autoCommit->手动提交offset。
Kakfa:手动提交offset
原则:采用同步的方式,在消息被消费完成,也就是本地事务执行完后提交消息,移动偏移量。
如何保证消息幂等
MQ产品并没有主动提供解决幂等的机制,需要由消费者自行控制。
RocketMQ中可以给每条消息分配一个ID,作为判断依据,但不保证全局唯一,不推荐。
建议使用带业务标识的ID,来进行幂等判断,如OrderID,统一ID分配。
如何保证消息有序
MQ只需保证局部有序,不需要保证全局有序。例如一个聊天窗口和整个QQ消息。
关键在于,单机下,队列可以先进先出保证有序,但在分布式状态下,有多个队列。
所以要保证生产者把一组消息放到同一个队列中,而消费者依次消费该消息组的所有消息
RockeMQ:
有完整设计,生产者中MessageSelevtor可保证,消费者需要注册一个registerMessageListener
RabbitMQ:要保证一组消息只对应一个队列,并且一个队列只对应一个消费者
Kafak:生产者可以将消息分配到同一个partition。Topic下只由同一个消费者消费