MQ消费端的幂等

MQ消费端的幂等

MQ消费端在接收到MQ消息之后按照业务key(uuid)进行防重,达到消费的幂等性。

业务场景

用户在使用白条优惠劵打白条支付订单后,如果用户整单退款,需要给用户补发优惠劵。白条异步处理系统监听白条退款MQ消息进行整单退退劵操作。对于一笔订单,整单退之后,用户的优惠劵只能补发一次。因此需要对MQ消费做防重幂等操作。

消费幂等的必要性

因为网络会发生抖动,MQ消费端和生产端都可能会出现超时,这样MQ就会出现重复发送和重复消费的情况,因此需要做到消费幂等。防止因此可能产生的资产损失。

整单退退劵的幂等

异步处理系统在接收到退款消息之后,会判断当前订单是否已经整单退款,如果已经整单退款,首先会恢复用户的参与次数(库存),然后会写退款流水记录(refund_record)。这两个步骤的操作是一个事务。退款流水记录的'uuid'字段用来防重(加唯一索引),'uuid'的生成规则为'userId' + 'orderId'。这样在MQ重试或者并发时spring会抛出DuplicateKeyException。我们捕获这个异常,如果是这个异常,默认MQ消费成功。这样就可以做到MQ消费的幂等性。简单地说,就是通过数据库的唯一索引来保证MQ消费的幂等。 流程图如下:

### MQ 消息队列中的等性处理 为了确保消息队列(MQ)中消息的等性,即防止重复消费带来的副作用,在设计系统时需考虑多种技术手段。当前流行的几种MQ如RocketMQ、Kafka、RabbitMQ、ActiveMQ等都采用至少一次交付机制(at least once delivery)[^1],这意味着每条消息会被成功发送给订阅者至少一次,但也可能多次。 #### 使用 Redis 缓存作为去重工具 一种常见的法是在接收端引入外部存储服务——例如Redis缓存——用于记录已处理过的消息ID或其他唯一标识字段。当接收到新消息时先查询此缓存;如果存在,则认为该消息已被处理过而忽略之;反之则正常执行业务逻辑并更新缓存状态[^3]。 ```java // Java伪代码展示如何利用Redis实现简单的等性检查 public void processMessage(String messageId, Message message){ Jedis jedis = new Jedis("localhost"); String key = "processed:" + messageId; if (!jedis.exists(key)){ try { // 执行实际业务操作... // 设置key有效期为一天 jedis.setex(key, 86400, "true"); } finally { jedis.close(); } } } ``` #### 数据库层面设置唯一键约束 对于某些特定类型的业务数据来说,可以在数据库表结构上直接设定相应的唯一索引来达到相同的效果。每当尝试插入一条新的交易记录之前都会自动触发数据库级别的验证流程,以此杜绝因网络波动等原因造成的重复提交现象发生。 ```sql CREATE TABLE orders ( id INT NOT NULL AUTO_INCREMENT, order_no VARCHAR(50), ... PRIMARY KEY (id), UNIQUE INDEX idx_order_unique(order_no) ); ``` #### 应用层内嵌入等令牌(Token) 除了依赖第三方组件外,还可以在应用程序内部构建一套完整的等控制系统。通常情况下会涉及到生成唯一的等Token,并将其附带至每次请求当中。服务器端在接受到客户端发来的指令之后便会依据这个特殊参数来进行判断是否存在未完成的任务实例正在等待确认或是已经完成了相应的工作流节点。 ```python import uuid def generate_idempotent_token(): return str(uuid.uuid4()) class IdempotencyHandlerFactory: handlers = {} @staticmethod def register_handler(event_type, handler_class): IdempotencyHandlerFactory.handlers[event_type] = handler_class @staticmethod def get_handler(event_type): return IdempotencyHandlerFactory.handlers.get(event_type) ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值