消息队列摘要

消息队列摘要

1,为什么要使用消息队列

解耦、弹性伸缩、冗余存储、流量削峰、异步通信、数据同步

(1) 解耦

将消息写入消息队列,需要消息的系统自己从消息队列中订阅,原系统不需要做任何修改。

(2) 异步

将消息写入消息队列,非必要的业务逻辑以异步的方式运行,加快响应速度

(3) 削峰

并发请求到消息队列,业务系统按照实际处理能力从消息队列拉去数据。

2,使用了消息队列会有什么缺点

系统可用性降低: 消息队列如果宕机,系统直接崩溃,因此,系统可用性降低

系统复杂性增加: 要多考虑的问题,比如一致性问题、如何保证消息不被重复消费,如何保证保证消息可靠传输。因此,需要考虑的东西更多,系统复杂性增大。

3,消息队列如何选型

1506330751030_7532_1506330753496.png

中小型软件公司:建议选RabbitMQ
大型软件公司:根据具体使用在rocketMq和kafka之间二选一

4,如何保证消息队列是高可用的

参考具体的消息队列高可用方案

5,如何保证消息不被重复消费

即保证消息队列的幂等性。

正常情况下,消费者在消费消息时候,消费完毕后,会发送一个确认信息给消息队列,消息队列就知道该消息被消费了,就会将该消息从消息队列中删除。只是不同的消息队列发送的确认信息形式不同,例如RabbitMQ是发送一个ACK确认消息,RocketMQ是返回一个CONSUME_SUCCESS成功标志,kafka实际上有个offset的概念,简单说一下(如果还不懂,出门找一个kafka入门到精通教程),就是每一个消息都有一个offset,kafka消费过消息后,需要提交offset,让消息队列知道自己已经消费过了。那造成重复消费的原因?,就是因为网络传输等等故障,确认信息没有传送到消息队列,导致消息队列不知道自己已经消费过该消息了,再次将该消息分发给其他的消费者。

解决:

  • (1) 拿到这个消息做数据库的insert操作,分配这个消息一个唯一主键,如果出现重复消费,则会导致主键冲突。
  • (2) redis的set的操作,无论set几次结果都是一样的,set操作本来就算幂等操作。
  • (3) 消费记录,以redis为例,给消息分配一个全局id,只要消费过该消息,将<id,message>以K-V形式写入redis。那消费者开始消费前,先去redis中查询有没消费记录即可。

6,保证消费的可靠性传输

  • (1)生产者丢数据
  • (2)消息队列丢数据
  • (3)消费者丢数据

如何保证消息的顺序性

通过某种算法,将需要保持先后顺序的消息放到同一个消息队列中(kafka中就是partition,rabbitMq中就是queue)。然后只用一个消费者去消费该队列。

参考:

【原创】分布式之消息队列复习精讲

消息中间件选型分析:从Kafka与RabbitMQ的对比看全局

常用消息队列介绍与对比

消息队列及常见消息队列介绍