【消息队列】消息队列常见面试题总结

目录

一、谈谈你对消息队列的理解

二、消息队列的应用场景

三、常见的消息队列有哪些

四、如何保证可靠性传输(消息不丢失)

五、如何保证消息的完整性

六、如何保证消息不重复消费

七、如何保证消息的顺序性


一、谈谈你对消息队列的理解

消息队列是一个按照先进先出原则的一个容器。用于对系统中产生的消息进行存放于消费。

消息队列的本质其实就是一个生成者-消费者模型。由生产者发送消息存储在消息队列中,消费从消息队列中获取。


二、消息队列的应用场景

异步处理短信通知、app推送、用户注册等。

流量控制比如在秒杀场景下,该商品的数量为100,当消息队列的数量达到100时,不再生产秒杀成功的消息,直接返回秒杀失败给用户。

服务解耦生产者只管将数据分发给消息队列,而消费者只需要根据需求到消息队列中获取即可,不需要就取消消息队列的消费。

发布订阅用户需要先去注册订阅消息,才能收到消息队列中的消息,进行消费。

高并发缓冲将消息放入消息队列中,降低高峰数据对后端的短暂缓冲。


三、常见的消息队列有哪些

常见的消息队列一共有三种:RabbitMQ、RocketMQ、Kafka等。

RabbitMQ是基于erlang开发的消息队列,并发能力强、性能好、延迟低(可达到微秒级),单机的吞吐量可达到万级,基本不会丢失消息。

RocketMQ是基于java开发的消息队列,支持分布式部署,扩展性好,单机吞吐量可达到十万级,经过参数优化配置可做到0丢失。

Kafka功能简单,只支持基本MQ功能,它最大的优势在于专为超高吞吐量的实时日志采集,实时数据同步、实时数据计算等场景,单机吞吐量可达到十万级。


四、如何保证可靠性传输(消息不丢失)

消息队列也采用ACK确认机制,就是当消费者确认消息已经被消费处理,则会发送一个ACK给消息队列,消息队列在接收后就会删除这个消息了。

如果消费者宕机或者关闭,消息队列没有接收到ACK确认,则会认为这个消息没有被处理,会将这个消息从新发给其他消费者。


五、如何保证消息的完整性

通过事务机制,生产者可以将消息封装在同一个事务中,只有当所有操作完成,才会提交事务,如果某个操作失败,整个事务会进行回滚,从而保证消息的完整性和一致性。


六、如何保证消息不重复消费

当消息消费完毕后,消费者会发送一个ACK确认消息给消息队列,消息队列就知道该消息被消费了,就会将该消息从消息队列中删除,但如果消费者发送的消息因为网络传输等问题,没有发送给消息队列,消息队列无法确认消息是否被消费,就会继续将消息交给其他消费者。

解决方案保证消息的唯一性,就算多次传输,不要让多次消费带来影响,保证消息的幂等性(用户对统一操作发生一次或多次的结果是一致的)):    

        1、消费一条消息就往数据库中插入一条数据,并设置唯一索引,如果一个消息被消费两次,就会因为数据的唯一索引导致插入失败,从而保证数据的正确性。

        2、消费一条消息,在Redis中做set操作,set操作本身具备幂等性。


七、如何保证消息的顺序性

RabbitMQ产生顺序错乱的原因是因为消费者通常是集群部署,多个消费者会同时执行不同消息,而执行的时间不同,导致最终执行binlog的顺序错乱。

解决方案

        创建多个队列。每个消费者固定消费一个队列的消息,生成发送消息时,同一个订单的消息发送到同一个队列中。

RocketMQ每个Topic可以指定多个消息队列,当我写入消息时会把消息均匀发给不同的消息队列,而消费者同时在不同的消息队列中获取消息,由于执行速度不同,导致最终执行binlog的顺序错乱。

解决方案

        只需将同一个订单的消息发送到同一个消息队列即可。

Kafka因为生成者在写入的时候会指定一个key,而通常我们会用订单号来做这个key,当消费者进行消费时,发现同一个key的多条消息,就会使用多线程处理,来提高速度,由于最终处理速度不同,执行binlog的顺序错乱。

解决方案

        可以在线程处理前,增加一个内存队列,将同一订单的消息放在同一个内存队列中,每个线程只负责一个内存队列。


注:本篇文章都是我自己的理解,可能用词和语句不够严谨,如有错误请评论指正,谢谢!(持续更新中......)

你可能感兴趣的:(java面试题总结——持续更新,rocketmq,rabbitmq,kafka,消息队列,MQ,面试题,java)