Redisson分布式锁,加锁代码完全正确,但是却没有起到锁的作用。
首先说明一下,这里的加锁代码是正确的,不存在因为加锁错误,锁失效的问题。那么锁是正常有效的,为什么没有起到锁的作用呢。下面先说一下我的业务场景:
这里的问题存在于支付场景,用户支付完成之后,为了确保安全快速的修改用户的订单数据,一个是第三方支付公司的回调,另外一个方面就是通过定时任务主动的轮询进行订单的查询。两条线同时确保数据能够安全快速的获取到用户的支付数据,这个时候就需要使用到锁了,那么这个锁是用在什么地方?
两条线确保数据快速安全的,但是修改数据的只能是一条线,否则容易导致重复修改操作订单数据,导致订单数据的错误,所以这个时候要上锁,当任意一条线先修改订单之前,要上锁锁住订单,那么其他线暂时获取不到锁,锁里面先查询订单是否处于支付中的状态,如果是那么修改为支付成功,之后释放锁;这个时候另外一条线就可以获取到锁了,进去判断支付状太已经是支付成功直接退出。
运行过程中,总是出现因为重复修改数据导致的错误,添加日志发现,每次进去锁之后查询出来的数据都是支付中的状态(即使确定前一条线已经修改为支付成功,但是这条线依旧查到支付中),然后两条线的执行时间间隔很短,但是能够确定的是锁是没有问题的,锁的执行确定是在上一个订单锁释放之后才执行的。那么原因到底是什么呢?
问题的解决是经过几天时间的监测以及猜测才找到,猜测过程后面说,这里先说明一下我这里遇到的情况。
这两种情况都是比较碰巧的情况下才会出现,尤其是缓冲这个。但是当订单量足够大的时候就不是碰巧了,而是必然会出现的错误。
在解决问题的过程中除了上面两种原因还有过了一个关于错误原因的猜测,但是目前无法进行测试证明,仅仅是一个猜测。
首先便是redisson分布式锁是一种可重入锁,也就说一个如果是一个线程,可以重复进入这个锁。所以个人猜测有没有可能执行定时任务和回调方法的是同一个线程。因为定时任务和回调方法都是从线程池中获取线程的,虽然说线程被激活获取后,不在闲置队列,无法被再次获取,但是有没有可能县城在执行过程中停个几毫秒(类似sleep),从而被其他方法获取执行,导致执行两个方法的是同一个线程。
这个只是个人的一种猜测,请了解的兄弟指点。