什么是消息队列:
消息队列是应对系统崩溃,服务处理能力有限,链路耗时长尾,日志如何处理的场景下的一个解决方案
- 消息队列有效地解决了订单系统内请求异步批量处理问题,解决了不同模块之间数据的交换和共享
消息队列的用户是谁?
需要用到消息队列场景的业务研发,测试,运维工程师
消息队列的应用场景:
-
解耦:发送者和接受者不需要受对方限制,只需要确认消息,
- 搜索行为记录和点击行为记录的部分通过消息队列处理
- 订单系统:用户下单之后消息写到消息队列,返回下单成功;
- 库存系统,订阅下单消息,获取下单信息,进行库存操作;
-
削峰:面对海量的请求,只处理前几个,比如秒杀,抢红包等
- 高峰过去可以慢慢处理积压请求,如果消息队列长度大过最大数量可以直接抛弃用户请求或者跳转到错误页面。
-
异步:将操作一起完成,提高处理效率,不需要处理方相应,减少无效等待的时间
- 注册信息入库成功之后,写入到消息队列,然后异步读取和发送邮件和短信
-
发布订阅:一条消息支持广播给多个消费者
业界对标
开源Kafka,AWS SQS,阿里RocketMQ,开源Pulsar,美团Mafka,开源RabbitMQ
消息队列如何解决消息丢失问题
-
要保证消息不丢失,可以从三个阶段进行防范:
-
生产者保证不丢消息:采用同步方式发送消息,消息返回成功状态,就表示消息正常达到了存储端的Broker。异常或者是非成功状态可以重试;
- 也可以使用事务消息,RocketMQ的事务消息机制就是为了保证零丢失来设计的。
-
存储端不丢消息:确保消息持久化到磁盘,即刷盘机制
- 同步刷盘:只有持久化到磁盘才会返回一个成功的ACK响应
- 异步刷盘:只要消息写入PageCache缓存,就返回一个成功的ACK响应。
-
消费者不丢消息:消费者执行完业务逻辑,再反馈会Broker说消费成功,这样才可以保证消费阶段不丢消息。
-
消息队列如何保证消息的顺序性。
- 消息序列号,发送完之后等ACK。但是这样的吞吐量太低,一般保证消息局部有序即可。在发消息的时候制定Partition Key,Kafka对其使用Hash计算,多消费者单线程消费指定的Partition。
消息队列有可能发生重复消费吗?如何幂等处理?
- 会,进行事务性保证,没有操作完进行回滚
- 搞个本地表,带唯一业务标记的,利用主键或者唯一性索引,每次处理业务,先校验一下就好啦。又或者用redis缓存下业务标记,每次看下是否处理过了。
如何处理消息队列的消息积压问题
-
消息积压是因为生产者的生产速度大于消费者的消费速度。遇到消息积压的问题,我们需要先排查,是不是又bug产生了。如果不是不管,我们可以优化一下消费的逻辑。
- 一条一条处理,改为批量处理消息
- 水平扩容,增加Topic的列数和消费及其的数量,提升整体消费能力。
- 紧急临时扩容
消息队列技术选型,Kafka还是RocketMQ,还是RabbitMQ
- RabbitMQ是开源的,比较稳定的支持,活跃度也高,但是不是Java语言开发的。
- 很多公司用RocketMQ,是阿里出品的。
- 如果是大数据领域的实时计算、日志采集等场景,用 Kafka 是业内标准的。
消息中间件如何做到高可用?
多副本保障消息存储的可靠性,单副本当即不会影响整个集群的消息转发。leader选举
如何保证数据一致性,事务消息如何实现
- 生产者产生消息,发送带MQ服务器
- MQ收到消息后,将消息持久化到存储系统。
- MQ服务器返回ACk到生产者。
- MQ服务器把消息push给消费者
- 消费者消费完消息,响应ACK
- MQ服务器收到ACK,认为消息消费成功,即在存储中删除消息。