公众号:架构师与哈苏
关注公众号进入it交流群! 公众号:架构师与哈苏 不定时都会推送一些实用的干货。。。

普通业务控制幂等性

1.mysql唯一索引

2.token机制(请求前生成一个token,请求时携带这个token,如果这个token在redis中没有则继续,有则 有请求进行中)

3.mysql悲观锁,乐观锁(推荐使用乐观锁)

4.分布式锁(redis,zookeeper)

问题的原因

我看先来看下整个流程,怎么会出现重复的消息呢?
生产者 -> MQ -> 消费者

1.生产者发送了多条同样的消息到MQ

2.一条消息消费了多次(在生产者只发送了一条消息的情况下,消费者消费完成,再给MQ发生消息确认这条消息消费完成,但是网络异常或服务中断,MQ没有收到确认。此时MQ不会删除此消息,下次再把这条消息给到消费者)

解决方案 生产者重复投递

在消息生产时,MQ内部针对每条生产者发送的消息生成一个inner-msg-id,作为去重和幂等的依据(消息投递失败并重传),避免重复的消息进入队列;

AMQP.BasicProperties.Builder builder = new AMQP.BasicProperties.Builder();
        builder.messageId(String.valueOf(UUID.randomUUID()));

解决方案 消费者重复消费

在消息消费时,要求消息体中必须要有一个bizId(对于同一业务全局唯一,如支付ID、订单ID、帖子ID等)作为去重和幂等的依据,避免同一条消息被重复消费。

1.新增场景: 拿到消息去数据库新增,添加mysql唯一索引,就会导致主键冲突,避免数据库出现脏数据。

2.修改场景: 让生产者发送消息时,每条消息加一个全局的唯一id,然后消费时,将该id保存到redis里面。消费时先去redis里面查一下有么有,没有再消费。

posted on 2021-05-10 14:13  公众号/架构师与哈苏  阅读(311)  评论(0编辑  收藏  举报