并发问题汇总

1、取消订单和支付订单并发问题

取消订单的定时任务和订单支付的业务会出现并发问题。即已经被取消的订单可能会被误支付,或者恰好订单支付完时,被取消订单。
解决方法:

  1. Redis的SETNX命令可以用于实现分布式锁,避免多个线程同时修改同一个数据,从而保证并发安全。控制订单已取消就不能支付,已支付就不能取消。

可以使用SETNX命令在Redis中设置一个键值对,键为订单ID,值为一个唯一的标识符,来实现分布式锁。在修改订单状态之前,先使用SETNX命令判断该订单ID是否已经被锁定。如果该订单ID已经被锁定,则表示有其他线程正在修改该订单,当前线程则不能修改改订单。如果该订单ID没有被锁定,则可以将其锁定,并进行状态修改操作。

**需要注意的是:**在使用SETNX命令时,需要确保锁的过期时间不会太长,否则可能会导致锁定时间过长,影响系统性能。可以通过设置过期时间或者使用Redisson等分布式锁组件来解决这个问题。其次要处理宕机、代码异常所带来的死锁、误删锁问题。

  1. 通过Redisson的tryLock()方法,不太好,因为取消订单操作是一个定时任务,批量修改操作,且Redisson是串行化操作,不能并行执行,效率较低。
// 获取Redisson客户端实例
RedissonClient redissonClient = Redisson.create();

// 获取分布式锁对象
RLock lock = redissonClient.getLock("order:" + orderId);

// 尝试获取锁,最多等待5秒
boolean locked = lock.tryLock(5, TimeUnit.SECONDS);
if (locked) {
    try {
        // 执行订单状态修改操作
    } finally {
        // 释放锁
        lock.unlock();
    }
} else {
    // 获取锁失败,处理异常情况
}

在上述代码中,我们首先使用Redisson.create()方法获取一个Redisson客户端实例,然后使用getLock()方法获取一个分布式锁对象。在修改订单状态之前,我们使用tryLock()方法尝试获取锁,并设置了最多等待5秒的超时时间。如果成功获取锁,这说明有线程在修改订单状态,如果没有获取到锁,则lock()加一下锁,再执行订单状态修改操作,最后释放锁;如果获取锁失败,则处理异常情况。

需要注意的是,Redisson会自动为获取到的锁设置一个过期时间,以避免锁一直被占用。在使用Redisson时,您还可以根据需要自定义过期时间、设置可重入等特性。

  1. 加入乐观锁机制,即在修改的时候加一个where条件,where order_status = ‘未支付’

2、订单超时取消设计

使用消息队列
思路
我们可以采用 rabbitMQ 的延时队列。RabbitMQ 具有以下两个特性,可以实现延迟队列

RabbitMQ 可以针对 Queue 和 Message 设置 x-message-tt,来控制消息的生存时间,如果超时,则消息变为 dead letter

RabbitMQ 的 Queue 可以配置 x-dead-letter-exchange 和 x-dead-letter-routing-key(可选)两个参数,用来控制队列内出现了 deadletter,则按照这两个参数重新路由。结合以上两个特性,就可以模拟出延迟消息的功能

优点:
高效,可以利用 rabbitmq 的分布式特性轻易的进行横向扩展,消息支持持久化增加了可靠性。

缺点:
本身的易用度要依赖于 rabbitMq 的运维.因为要引用 rabbitMq,所以复杂度和成本变高。

3、订单重复提交问题解决

提交订单时,在redis中存一个字符串。按照用户id+排序好的每一个商品id来拼接。如果商品id太多也可以直接转成md5
,重复提交订单时,判断key是否存在。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值