redis分布式锁的复杂实现

一,业务场景,秒杀系统

1,实现分布式锁

2,不能超卖

二,实现逻辑

1,synchronized,在抢购方法上加同步锁synchronized,弊端:只使用单机环境;很慢。只有所有逻辑执行完,下个人才能购买,把东西卖完耗时长

2,redis锁,在方法内部对商品加锁,解锁成功,继续执行购买操作,最后解锁。但是productId相同,不还是只用一个人能执行业务逻辑,其他用户只有等待吗?(暂不考虑为什么这样快)

三,加锁实现

3.1)如下,直接加锁,会导致两个问题

1,可能死锁,服务挂了,finally也没法释放

2,

 3.2)针对上面的问题,直接加个过期时间不就行了,实际上是这样实现的,如下图

那中间这一坨代码实现什么功能?

1,设置过期时间,过期了,其他线程立即加锁执行购买

2,?

逻辑

1,线程1,加锁成功,返回true,下面代码不执行。这时候服务挂了,不还是死锁吗,没有过期时间?

假设起始时间为1000ms,即线程1进来时间

key:100

value:1000+100ms = 1100

线程1("100", "1100")

2,线程2,过了200ms,如果另外一个线程过来,当前时间1200

线程2("100", " 1300")1000+200+100 = 1300

currentValue:1100

当前系统时间:1000+200 = 1200 1100<1200,说明线程1过期了。

这时候业务可能没执行完(怎么办),且锁还没释放,在此获取时get/getAntSet时,发现锁过期了,才删除原来的锁,业务没执行完怎么办?锁已释放,是不是其他用户可以购买?是不是可以把值往大了设,确保业务逻辑执行完,finally释放锁(弊端:死锁了怎么办)(先不管)

3,如果线程1没过期,线程二返回false,加锁失败,不会执行购买逻辑,返回排队中...........

4,线程1过期了,线程2执行getAntSet,注意这里只有一个线程能执行成功(可能同时进来两个线程都执行到这里)

oldValue:1100

当前key value("100", "1300")

5,比较老值和当前值

老值:1100 

currentValue:1100

相同,返回true,线程1失效时,线程2加锁成功(如果线程1逻辑没执行完,线程2也去执行业务逻辑,会不会导致超卖?)

6,然后呢,上面这些说明什么问题

实现了,如果前面线程过期,后面线程可以,立即加锁执行购买行为

然后呢,主要说明的是这种场景

线程1持有锁,并发情况下,线程2,线程3同时进入加锁方法,且value相同

线程1("100", "1100")

线程2,线程3("100", "1300")

如果当前时间1200,线程1过期,线程2设置了当前key value("100", "1300")

老值:1100 

currentValue:1100,相同加锁成功

重要的是对于线程3来说,

currentValue:1100

oldValue:应该是线程2的值,1300

明显不相同,加锁失败,等待线程2执行。

巴拉巴拉差不多说完了,现在想想中间这坨代码干啥的?

1,过期了,其他人能够立刻购买成功

2,过期了,并发时,只要一个人能购买成功。如果不加这坨呢,直接加锁时加个过期时间,不过期时,其他线程过来返回false,有啥问题吗,又绕回去了。

想不通?

其他实现逻辑

1,判断是否被锁 isLock

2,是,不执行

3,否,加锁

4,释放锁

加锁方法返回Boolean,具体实现如下 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值