理解消息队列的持久性,可靠性,幂等性

持久性

一些下单任务,例如付完钱后异步下单,为啥我们主流都是使用mq来做异步,而不是使用线程池来做异步呢?明明都能做异步

因为如果我们的Java程序宕机了,那么我们的异步任务没完成完,那就直接结束了

如果我们使用mq的话,它是Broker,它有持久化功能,文件可以存储到MQ内部,本地文件持久化

这样子我们就能重试,保证消息消费


可靠性

mq有重试机制,如果消息发送失败的话我们可以重试,而用线程池这种的话要写一对冗余的代码

我们保证消息能成功发送

可靠性体现在三个地方

确保生产者发送给Broker

失败场景:网络波动或者mq宕机等,导致发送不过去

确保Broker发送给消费者

失败场景:网络波动或者mq宕机等,导致发送不过去

确保保证消费者能成功消费到消息

默认:发送到消费者mq就标记消费成功,也就是成功发送到消费者就直接ack

失败场景:我们可能消息队列发送给消费者成功,但是java程序没执行完代码就宕机的,但是此时我的消息队列已经发送消息了,所以它会结束表示成功消费,但是其实我们java程序没运行完,本质上还是消费失败。

所以我们有一个手动ack机制,也就是我们执行完,再返回一个ack告诉消息队列我们发送成功了

不然我们就重试3次(代码要自己写)

我拿RabbitMq举例子,可以看一下我的其他文章

RabbitMq手动ack的超简单案例+Confirm和Return机制的配置和使用_rabbitmq 手动ack-CSDN博客


幂等性

重复消费问题

幂等性就是保证消息的唯一性,防止消息被重复消费

可能因为网络故障波动或者其他原因,导致我们的mq重复发送多次请求给消费者,导致我们的消费者重复消费。

如果是下单那么我们的单号可能有重复的5个,这样子明显是不行的

解决方案

我们要弄消息的唯一ID(唯一标识)

例如把消息的唯一标识改成UUID+时间戳,那么怎么样都不会遇到ID相同的情况

为什么要这样弄呢?

我拿RabbitMq举例子,RabbitMq的消息的唯一ID是通过队列名,交换机名和消息内容生成的。

那我们发送消息内容相同,那么我们的自动生成的ID不就一样了?

所以我们要改一下我们的ID生成策略

然后我们把这个ID存到Redis里面去,每次消费前去判断Redis里面是否存在这个ID。

如果有那么就消费过了,我们不执行,防止重复下单。

如果没有,那么就是我们没消费过,我们直接下单就行了。

这样子就保证了消息的幂等性


这三个性质是共通的,可以延伸到其他的消息队列,例如Kafka和RocketMq

  • 6
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值