自行编写分布式锁解决优惠券一人一单问题的思路(集群版)

在集群模式下,有多个服务器,当同一用户发起多次请求时,有几率分配到不同的服务器上,不同的服务器是不同的锁监视器,导致同一用户的多次请求都可以获取锁

分布式锁

本质是多个线程只有一个锁监视器,分布式系统或者集群模式下多进程可见并且互斥

基于Redis的分布式锁

获取锁,确保只有一个线程能够获取锁

释放锁,如果手动释放,假如线程获取锁后,服务器宕机,其他线程等待获取锁,获取锁的线程等请求释放锁,此时会进入死锁状态。所以要加入超时时间

如果线程刚刚获取锁,还未执行加入超时时间操作,服务器就宕机,此刻还是会进入死锁状态,所以必须保证获取锁和设置超时时间这两个操作是不可分割的,即原子性

版本一

获取锁使用set key value nx ex time语句,保证了原子性,锁的是线程id,释放锁使用del语句

版本一存在的问题:

存在误删问题,假如线程一的业务阻塞,超过了超时时间,然后锁自动释放,此时线程二获取到锁,开始执行,假如在线程二执行过程中,线程一的业务完成,此时按照线程一的流程会直接执行del释放锁,线程二还在执行,会有安全问题

解决方法:

del前判断锁标识,原来是用纯粹的线程id来作为线程标识,现在可以用UUID+线程id来做线程标识,UUID用于区分不同的jvm,线程id用于区分不同的线程,在锁释放之前先进行判断,判断redis中的锁标识和现在想释放锁的线程是否为同一个

**但是现在会出现新的问题:**判断锁标识和释放锁是两个操作,当判断完锁标识后,此时因为jvm本身的原因,比如垃圾回收,可能会阻塞业务,如果阻塞时间足够长,超过了设置的锁超时时间,其他线程会获取锁,执行相应业务。当阻塞结束时,原先的线程因为判断过锁标识,现在会释放锁,导致线程安全问题

新问题解决方法:

使用lua脚本来保证判断锁标识和释放锁的原子性

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值