00:00
上节课呢,我们对支付通知文档当中提到的重复的通知进行了处理,那么这节课呢,我们要对数据呢进行并发控制,那为什么要进行并发控制呢?我们来读一下这段内容哈,在对业务数据进行状态检查和处理之前,要采用数据锁进行并发控制,以避免函数重入造成的数据混乱。什么意思呢?我们来看一下上节课我们写的这段代码,那大家想象一下,现在虽然我们通过这样的一个状态判断来避免了我们重复的通知呢,对我们数据的一个重复的处理,那大家有没有想过,假设说现在有两个通知同时到达了这个业务方法,并且同时执行了这段代码,然后同时来到第154行,将会发生什么?那么依然会有两次的日志记录会被记录,所以说呢,我们来模拟一下这个过程,那么我们模拟这个过程的主要的手段呢,依然是让现成睡眠哈,我们还是可以用time unit让他睡五秒啊,我们check一下。
01:13
啊。这块呢,我们主要是模拟通知并发,那接下来呢,我们来重新启动一下服务器,看一看上节课已经被我们解决的。重复通知对记录支付日志的这样的一个影响,是不是又出现了?好,我们先确认一下数据库啊,里面的数据呢是没有的,这样的话方便我们做测试的时候判断。那我们重新的发起一笔支付。好,我输入密码。好,支付已经完成,我们来看一下我们的日志,那么在日志里面呢,我们找到我们的通知。
02:09
调用统一下单API后面呢,就是支付通知,那支付通知。它一定会被重复的调用啊,因为呢,在我们的项目当中,不但有这个地方的睡眠是吧,还有。还有这个地方的睡眠啊,所以说呢,它一定会重复的调用的,但是呢,其实上堂课我们已经对这个延迟应答呢,进行了一个处理,所以呢,通过我们上堂课的处理呢,那我们的数据库当中呢,就不会有重复的支付日志了。诶,你会发现这堂课啊,经过我们在这个地方又模拟了一个通知并发,那么重复的支付日志是不是又出现了,这回呢,出现了两条日志,因为呢,我们有两个通知同时到达了我们当前的。
03:09
这个代码块当中,然后呢,同时判断了订单状态为未支付,并且同时执行了更新订单状态和记录支付日志的这样的一个过程,所以怎么解决这个问题呢?那么解决这个问题的解决方案呢,就是使用数据锁。在这个位置,他说在对业务数据进行状态检查和处理之前,要采用数据所进行并发控制,以避免函数重入造成的数据混乱,所以现在呢,我们要做这件事情啊,那么在哪加锁呢?我们要把所加的状态检查以及处理数据的外面好。所以在这个位置呢,我们。写一下啊。
04:05
在我们的应用程序的上面加一把私有的就可以了啊,加一把安锁。可重入锁。好,接下来呢,我们在。刚才这个位置。使用锁呢,对数据呢进行并发控制,我们先尝试获取锁。好。好,我们把啊对数据的状态检查,以及对数据的处理呢,都放在我们的所里,所以这个位置呢,是尝试获取锁。
05:02
成功,也就是说返回成功。过去。则立即返回处。获取。失败则立即。返回boss。不必,它和我们的synchronized的区别呢,就是synchronized啊,如果啊,我们的这个线程到达这块没有获取到锁的话,那么它会一直等待,那么这个rerylo呢,通过trylo这个方法获取锁,如果没有获取到锁的话呢,他就立即返回失败,那么他就不浪费表情了哈,就该干嘛干嘛去了,就不会在这儿等待了啊。不必。一直等待锁的释放。
06:03
好,那么用这个锁呢,大家一定要记住,必须去主动的释放锁,所以呢,一般情况下我们会在这个位置。写一个T。TRY啊。在这个位置呢,我们来主动示范。Lock unlock。好,这样的话呢,我们就可以解决我们通知并发的问题了,所以接下来呢,我们再对我们的代码呢做一个测试,看一看经过这一次的优化之后,我们这面呢,会不会重复的记录支付日志,所以呢,我们先把支付日志呢删掉。好,我们重新启动应用程序。
07:10
我们等待它启动完成啊,还没有启动完成。好,已经启动完成了,那我们呢,刷新一下我们的支付页面。好,为了看得更清楚,我先把现在的控制台数据删掉。那么我们来再次发起一个支付。好,我的密码已经输完了啊,那么这面呢,又来到了我们的控制台,我们来看一下现在呢我们的通知。它实际上呢,确实也是重复的发生了,但是。我们通知过后的。更新订单状态和记录支付日志有没有重复的发生呢?你会发现没有,对不对啊好,我们来看一下数据库当中的数据,首先order info肯定是没有问题的啊,那我们来看一下payment info有没有多余的记录没有,所以呢,现在我们通过。
08:19
与lo啊,这个可重入锁,对我们的应用程序呢进行了并发控制。
我来说两句