程序员中间件IT面试

消息队列常见问题

2019-02-26  本文已影响80人  半亩房顶

消息队列缺点

应用场景分析

异步处理

应用解耦

流量削锋

消息队列模型

P2P/点对点模式(Queue;消息队列,发送者,接收者)

发布订阅模式(Pub/Sub;主题,发布者,订阅者)

消息队列选型

转自
ActiveMQ早期用的比较多,但是现在貌似用的都不是很多了,网上也没有大规模吞吐量的使用案例分析,社区也貌似不是很活跃了,如果是新项目不建议采用ActiveMQ。

RabbitMQ现在使用的较为多一些,社区活跃度也很高,功能也很强大,官方还提供了管理的web界面,性能也很好,但是RabbitMQ性能好的主要原因是因为使用erlang语言开发的,erlang语言貌似天生性能好,但对于我们java开发者来说,源码基本看不懂,更别提深入的研究了,不过spring推出了rabbit的支持,貌似还比较好用,比自己去封装实现并且去处理一些问题的要好多了。

RocketMQ现在开始用的人也比较多,很多人对于RocketMQ的看法是集成了Kafka和RabbitMQ的有点,是阿里开源的产品,貌似现在是捐赠给了Apache,其源码是java写的,功能十分强大并且是经过阿里大规模应用的,能经过阿里实践使用的一般来说可靠性和可用性都是相当高的,但是也存在一些小问题,现在RocketMQ虽然使用的人好像越来越多了,但是文档资料还是比较少,含金量不怎么高,并且阿里开源的有不维护的风险,就像dubbo中间也用2年没维护,有实力的团队应该没有什么问题,小公司小团队需要考虑一下使用RocketMQ。

Kafka就不多说了,Kafka可以说是业内标准,基本上大数据领域的实时计算、日志、数据处理都是用kafka,开源社区异常活跃,而且像现在阿里云、腾讯云都推出了Kafka的云服务,所以说Kafka就不说了,绝对没问题,放心大胆的用吧。

对比图

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

kafka RocketMQ RabbitMQ

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

正常情况下,消费者在消费消息的时候,消费完毕后,会发送一个确认消息给消息队列,消息队列就知道该消息被消费了,就会将该消息从消息队列中删除。只是不同的消息队列发出的确认消息形式不同,例如RabbitMQ是发送一个ACK确认消息,RocketMQ是返回一个CONSUME_SUCCESS成功标志,kafka实际上有个offet的概念,简单说一下,就是每一个消息都有一个offset,kafka消费过消息后,需要提交offset,让消息队列知道自己已经消费过了。

造成重复消费的原因,就是因为网络传输等等故障,确认信息没有传送到消息队列,导致消息队列不知道自己已经消费过该消息了,再次将消息分发给其他的消费者。
解决方案:
(1)比如,你拿到这个消息做数据库的insert操作,那就容易了,给这个消息做一个唯一的主键,那么就算出现重复消费的情况,就会导致主键冲突,避免数据库出现脏数据。

(2)再比如,你拿到这个消息做redis的set的操作,那就容易了,不用解决,因为你无论set几次结果都是一样的,set操作本来就算幂等操作。

(3)如果上面两种情况还不行。准备一个第三方介质,来做消费记录。以redis为例,给消息分配一个全局id,只要消费过该消息,将<id,message>以K-V形式写入redis.那消费者开始消费前,先去redis中查询有没有消费记录即可。

如何保证消息的可靠性传输

生产者丢数据

支持事务的队列,如RabbitMQ,可以开始事务,但是会造成吞吐量降低

消息队列丢数据

处理消息队列丢数据的情况,一般是开启持久化磁盘的配置。这个持久化配置可以和confirm机制配合使用,你可以在消息持久化磁盘后,再给生产者发送一个Ack信号。这样,如果消息持久化磁盘之前,rabbitMQ阵亡了,那么生产者收不到Ack信号,生产者会自动重发。

如何持久化

消费者丢数据

消费者丢数据一般是因为采用了自动确认消息模式。这种模式下,消费者会自动确认收到信息。这时rabbitMQ会立即将消息删除,这种情况下,如果消费者出现异常而未能处理消息,就会丢失该消息。至于解决方案,采用手动确认消息即可

如何保证消息的顺序性

如何解决消息队列的数据积压

上一篇下一篇

猜你喜欢

热点阅读