spring 多线程 事务的实际应用场景
大家好,我是烤鴨:
今天分享的是spring 多線程 事務的實際應用場景:
上一篇講了大概的原理,主要是針對事務的開始和執行過程(數據庫鏈接,隔離級別,threadlocal線程綁定)。
https://blog.csdn.net/Angry_Mills/article/details/82502288
?
下面從實際的角度分析一下。
以下場景的演示代碼地址:
https://gitee.com/fireduck_admin/demo-mutithread.git
1.? 模擬場景? ?
? ? 1.1 方法未加 Transactional 注解,new Thread 方式的主子線程 事務提交情況
?? ?主線程和子線程事務分別提交(主線程提交后子線程提交)
?? ?1.2 方法加 Transactional 注解,new Thread 方式的主子線程 事務提交情況
?? ?主線程和子線程事務一起提交
?? ?下面只考慮加注解方式的情況
?? ?1.3 主線程正常,子線程異常?
?? ?無論在new Thread 方式的子線程的run方法加不加 Transactional 注解,子線程都是以無事務方式運行
?? ?1.4 采用springboot的 Async 注解,主線程加事務注解,子線程不加事務注解
?? ?主線程和子線程事務一起提交
?? ?1.5 采用springboot的 Async 注解,主線程加事務注解,子線程不加事務注解,子線程異常
?? ?主線程和子線程事務都未提交
?? ?1.6 采用springboot的 Async 注解,主線程加事務注解,子線程加事務注解 @Transactional(propagation = Propagation.REQUIRES_NEW)
?? ?主線程和子線程事務分別提交(子線程提交后主線程提交)
?? ?1.7 采用springboot的 Async 注解,主線程加事務注解,子線程加事務注解 @Transactional(propagation = Propagation.REQUIRES_NEW),子線程異常
?? ?主線程和子線程事務都未提交
?? ?1.8 采用springboot的 Async 注解,主線程加事務注解,子線程加事務注解 @Transactional(propagation = Propagation.REQUIRES_NEW),主線程異常
?? ?主線程未提交和子線程事務提交
?? ?總結一下。
?? ?采用 異步注解的時候,配置Propagation.REQUIRES_NEW,主線程和子線程確實是兩個不同的事務,分別提交。
?? ?但是對于子線程的異常,卻兩個都回滾了。子線程由于異常回滾,這個是沒問題的。同時將異常拋給主線程,主線程也跟著回滾了。
?? ?我們可以認為多線程的事務是嵌套的,任何子線程的異常都會導致整個事務的事務回滾。
?? ?但是子線程如果執行完沒有異常,事務會直接提交,不管主線程是否異常。
2.? 實際場景
? ? ?之前遇到的場景是這樣的,用戶和我們發起支付是同步接口,這個時候還要請求第三方的支付接口(如支付寶的接口),這時候就有個問題了。
??? ?由于支付的異步回調如此之快,導致用訂單號去數據庫查找不到數據(數據還沒提交入庫)。
??? ?同一個service 做這個肯定不行,就想著把入庫的操作放到異步方法里做,主要保證調用第三方接口前數據庫已經入庫了(子線程事務提交)。
??? ?這時候就可以采用 上面 1.7 的做法,子線程比主線程優先提交,但是即便這樣也沒法保證子線程的執行一定比回調快。
?
3. ?改進
? ? 一般第三方的回調接口都有超時時間響應,他不希望你做任何的邏輯處理。只要接收到消息返回 success 即可。
?? ?所以將消息的接受和業務邏輯處理分開,接受到回調后返回成功,同時異步處理業務邏輯。
?? ?如果這個時候還沒入庫,把回調的唯一標識(訂單號和回調參數)放到緩存。
?? ?在子線程入庫后也做類似的操作,查詢緩存中的訂單號是否存在(存在說明回調先到了),再獲取回調參數,手動調用一次異步通知。
?? ?當然這種還是有可能出現極端情況,就是 回調方法剛查詢完,放緩存/子線程剛入庫,獲取緩存同時進行。導致緩存中還是存在訂單號。
?? ?這種極低概率的問題,可以間隔一段時間跑補償程序(1h 一次)。
?
總結
以上是生活随笔為你收集整理的spring 多线程 事务的实际应用场景的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java导出生成word(类似简历导出)
- 下一篇: iOS项目架构 小谈