限购(一人一单)问题解剖及解决方案

限购问题

限购问题是生活中很常见的,如某某手机限购不能超过几台,商品搞活动时每人购买不能超过1件…
这种问题看似很简单,但一个处理不好,就会出现超买问题

问题:活动产品,每个用户购买不能超过1个?

在这里插入图片描述
线程1进来先校验A客户是否下单过,此时是没有,在还未来得及生成订单,线程2进来校验A客户是否下单过,由于线程1事务还未提交,所以线程2的校验是通过的,最终两个线程都能提交,导致超买了;

解决方案:Java锁(单机)

以客户和产品的维度来加锁,使校验和生成订单成为一个原子操作;

解决方案:分布式锁(集群)

分布式锁可以使用Redis、Zookeeper、数据库方式来实现;

Redis实现分布式锁问题?

setnx

设置redis锁时,避免程序挂了,使锁释放不了,需要设置过期时间;
为避免设置锁后还来不及设置过期时间就挂了,需要锁和过期时间同时设置;

锁超时释放

线程1获取锁后,执行的时间太久,锁提前失效了,线程2又获取到锁进来,之后线程1执行完了,释放锁,此时的锁是线程2的锁,由于线程1释放了锁,线程3又能进来了,此时需要判断是自己的锁才能释放;
由于线程2获取锁进来,线程1事务还没有提交,导致两个线程最终都能提交,此时需要判断是自己的锁才能释放并且提交事务,如果不是则进行回滚;

使用 redisson 来实现分布式锁

redisson解决的问题

  1. 可重入锁:在锁里面再上一次锁
  2. 重试获取锁:获取锁时设置一个超时时间,在这个时间内,如果锁被释放了,可以尝试再次获取
  3. 锁续时:业务执行时间过长时,锁自动续时
  4. 主从一致:redis在做主从时,从节点同步锁可能有点慢,主节点突然就挂了,由于从节点还未来得及同步锁,就被选为做主节点,其他线程再进来又能获取到锁;redisson多主多从机制解决,设置锁时向多主写,在加锁时需要每对主从节点都没有才能加锁成功

总结

限购问题需要先校验再生成一条新的数据,使用单纯的数据库乐观锁是解决不了的,这种场景就需要使用悲观锁来处理

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值