幂等性
幂等性是数学和计算机上的某些运算性质,他们可以被多次应用,而不会改变初始应用的结果。比如-1进行绝对值之后变成1,后面不管怎样绝对值都是变成1。
比如我们通常会要求支付接口符合幂等性,多次调用同一个订单,同一个参数,对系统的影响是一样的(只能支付一次)。同一个订单,订单系统多次调用支付系统,支付系统只能进行一次扣款。
mq的幂等性指的是,同一条消息,多次消费,对系统的影响是相同的 ,市面上的mq基本都是只支持最多一次和最少一次。可靠性比较高的时候就使用最少一次,可靠性比较低的场景用最多一次。
最少一次的问题
- 当生产者发送消息给mq的时候,mq可能因为网络问题没有返回给生产者确认应答,生产者就会认为没有发送成功,导致发送过多,使得消费者处理多次。
- 也有可能mq发给消费者,消费者返回确认应答网络出现问题,也会导致mq向消费者发送多次。
解决方法(面试重点)
全局唯一id
给每条信息分配唯一的id,当消费者收到重复的消息,可以通过全局唯一id(比如uuid,或者自增id,业务id,时间戳+业务id)进行判定。消费者通过id进行判定,如果有已经消费过的,那就把消息进行抛弃。没有的话就把业务id存起来,比如数据库redis。
业务判定
比如判断数据库中是否有相关数据的存储,确保消息还没有被处理,然后才进行处理,比如看订单比如已经被取消了,如果已经被取消了,那不管怎么样都不进行处理。
顺序性保证
消费者消费消息的顺序和生产者生产消息的顺序相一致,比如生产者发送123,消费者消费123。如果消息没有丢失等等,才能保证消息顺序性。
同一时间对用户昵称进行修改,需要保证顺序性的保证,才能保证在多次修改的情况下能够最终修改成功。
打破rabbitmq的顺序性
多消费者
多个生产者发送消息顺序可以保证,但是mq接收消息的顺序不能保证,但是我们可以强制保证消费的顺序。多个消费者并行处理消息,相互之间并不相互影响。
网络波动
网络波动导致消息的ack出现问题 ,可能会重发,比如消费者1挂了,没有顺序消费消息。
死信队列
虽然排队排的早,但是因为某些原因没有成功发送给消费者,而是交给了死信队列。这时候后面的消息反而先消费,死信队列却没有消费
消息顺序性保证方法
局部顺序性保障
局部顺序性保证就是在一个队列(单个队列单个消费者)中要顺序处理,不能跳过,但是其他队列的处理相互之间不受影响,相互之间可以分别处理。
全局顺序性保障
全局性保证要保障每个队列(多个队列,多个消费者)都进行顺序性,比如要求是12345这样的顺序,不管这些消息分散在各个队列,都要按照这样的顺序进行消费。
单个队列,单个消费者。
分区消费,比如购买A商品,就可以通过一个订单一个订单号创建一个队列,这个订单的修改等都可以在一个队列中完成。
实际上rabbitmq没有实现分区算法,根据订单id进行hash算法,进行分散到多个算法,保证同样的订单id,进行算法分散之后,永远路由到某个队列。
消息积压(面试常考)
- 生产者生产速度比较快,导致消费者没时间消费,消息堆积在队列中。
- 消费者消费能力不足,消费者处理速度跟不上。
- rabbitmq服务器配置不行。
- 网络问题,导致队列中的消息没办法让消费者确认,就会导致某个消息没有收到确认一直堆积在队列口。
解决方法: