1.消息队列都有哪些使用场景:异步 解耦 削峰 从这个三个点举例说明假设的场景
2.项⽬⾥具体使用场景:保存操作是把数据存入到mysql的(系统之前是基于Oracle,新系统用的mysql,兼容新老系统可以同时使用),通过rabbitMQ,异步进行数据同步;
2.1 使用原因: 时效性是微秒级,延迟最低;消息可靠性高,基本不丢;基于erlang开发,并发性能很好;开源的,⽐较稳定的⽀持,活跃度也⾼;
2.2 kafka: 大数据领域,业内标准;
3.实际使用rabbitMQ工作模式:入门级 work queues
1、一条消息只会被一个消费者接收;
2、rabbit采用轮询的方式将消息是平均发送给消费者的;
3、消费者在处理完某条消息后,才会收到下一条消息。
4.如果不⽤ MQ 可能会很麻烦,但是你现在⽤了 MQ 之后带给了你很多的好处:异步 不用的话需要同步处理数据 额外开销增加方法调用时间 ;如果失败 影响了当前的保存操作; 解耦 剥离出来业务到另一个项目里去;
5.如何保证消息队列的⾼可⽤,不然MQ挂了项目就没法继续下去了:
基于 主从架构 实现⾼可⽤
单机模式:本机玩玩
普通集群模式:无高可用性 解决的是吞吐量增大 内部开销也大 因为只有一台存放实例和数据的机器
镜像集群模式:高可用
6.怎么保证消息没有重复消费(使⽤消息队列如何保证幂等性):
根据业务来处理:我们的业务下重复消费是没有关系的 我们就是想删除在保存的;其他的可以利用数据库的唯一性,或者自己加个唯一主键,然后保存到redis里,每次消费之前去redis查一下有没有存在这个id,等等
7.怎么处理消息丢失的情况:
3种信息丢失情况:
一,生产者:消息在传入工程中丢失
二,rabbitMQ:收到消息,暂时存在内存中,还没消费,自己挂掉了,内存中的数据丢失
三,消费者:消费到了这个消息,但是还没有来得及处理,就挂了,MQ又以为消息已经被处理了
解决生产者丢失消息:
可以开启 confirm 模式,在⽣产者那⾥设置开启 confirm 模式之后,你每次写的消息都会分配⼀个唯⼀的 id,然后如果写⼊了 RabbitMQ 中,RabbitMQ 会给你回传⼀个 ack 消息,告诉你说这个消息 ok 了。如果RabbitMQ 没能处理这个消息,会回调你的⼀个 nack 接⼝,告诉你这个消息接收失败,你可以重试。⽽且你可以结合这个机制⾃⼰在内存⾥维护每个消息 id 的状态,如果超过⼀定时间还没接收到这个消息的回调,那么你可以重发。
注意:不推荐使用事务机制,因为同步会导致后续的消息阻塞,得不偿失。
解决MQ丢失消息:
持久化有两个步骤:
第一个创建 queue 的时候将其设置为持久化这样就可以保证 RabbitMQ 持久化 queue 的元数据,但是它是不会持久化 queue ⾥的数据的。
第⼆个是发送消息的时候将消息的 deliveryMode 设置为 2就是将消息设置为持久化的,此时 RabbitMQ 就会将消息持久化到磁盘上去。注意:必须要同时设置这两个持久化才行。
还有⼀种可能,就是这个消息写到了RabbitMQ 中,但是还没来得及持久化到磁盘上,结果不巧,此时 RabbitMQ 挂了,就会导致内存⾥的⼀点点数据丢失。所以,持久化可以跟⽣产者那边的 confirm 机制配合起来,只有消息被持久化到磁盘之后,才会通知⽣产者 ack 了,所以哪怕是在持久化到磁盘之前,RabbitMQ 挂了,数据丢了,⽣产者收不到 ack ,你也是可以⾃⼰重发
消费者丢失数据:
关闭 RabbitMQ 的⾃动ack,调用api手动ack
8.如何保证消息的顺序性:拆分多个 queue,每个 queue ⼀个 consumer,就是多⼀些 queue ⽽已;