成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

@Transactional + @Async 有大坑!

開(kāi)發(fā) 前端
@Transactional 注解就像是一位嚴(yán)謹(jǐn)?shù)墓芗遥鼤?huì)創(chuàng)建一個(gè)原子代碼塊。在這個(gè)代碼塊里,所有的操作都被視為一個(gè)整體。

@Transactional 和 @Async 這兩個(gè)注解更是開(kāi)發(fā)者們常常使用的得力工具。然而,當(dāng)這兩個(gè)注解相遇,它們能否和諧共處,發(fā)揮出最大的效能呢?

相信很多開(kāi)發(fā)者都沒(méi)有深入思考過(guò)這個(gè)問(wèn)題。今天,就讓我們一起深入探討一下 Spring 框架中 @Transactional 和 @Async 注解之間的兼容性。

深入理解 @Transactional 和 @Async

@Transactional 注解就像是一位嚴(yán)謹(jǐn)?shù)墓芗?,它?huì)創(chuàng)建一個(gè)原子代碼塊。在這個(gè)代碼塊里,所有的操作都被視為一個(gè)整體。一旦其中某個(gè)操作出現(xiàn)異常,就如同多米諾骨牌一樣,所有已經(jīng)執(zhí)行的部分都會(huì)被回滾。只有當(dāng)這個(gè)原子單元中的所有操作都成功完成時(shí),才會(huì)通過(guò)提交操作正式生效。使用事務(wù)機(jī)制,我們可以有效地避免代碼出現(xiàn)部分失敗的情況,從而大大提高數(shù)據(jù)的一致性。

@Async 注解則像是一位充滿活力的短跑選手,它告訴 Spring,被注解的方法或類可以與調(diào)用線程并行運(yùn)行。當(dāng)我們從一個(gè)線程調(diào)用一個(gè) @Async 方法時(shí),Spring 會(huì)在另一個(gè)具有不同上下文的線程中啟動(dòng)該方法的執(zhí)行。這種異步執(zhí)行的方式可以顯著提高程序的執(zhí)行效率,尤其是在處理一些耗時(shí)的操作時(shí)。

在某些復(fù)雜的業(yè)務(wù)場(chǎng)景中,我們既希望代碼能夠保證數(shù)據(jù)的一致性,又希望能夠提高執(zhí)行性能。在 Spring 中,我們確實(shí)可以嘗試將 @Transactional 和 @Async 結(jié)合使用,以實(shí)現(xiàn)這兩個(gè)看似矛盾的目標(biāo)。但在實(shí)際操作中,我們必須格外小心,注意如何正確地使用這兩個(gè)注解。

@Transactional 和 @Async 能一起使用嗎?

1. 構(gòu)建示例應(yīng)用:銀行轉(zhuǎn)賬功能

為了更好地說(shuō)明事務(wù)和異步代碼的使用,我們以銀行的轉(zhuǎn)賬功能為例。簡(jiǎn)單來(lái)說(shuō),轉(zhuǎn)賬就是從一個(gè)賬戶中取出一定金額的錢,然后將其添加到另一個(gè)賬戶中。這一系列操作可以看作是對(duì)數(shù)據(jù)庫(kù)中賬戶信息的更新操作。

圖片圖片

我們的具體實(shí)現(xiàn)步驟如下:首先,使用 findById() 方法根據(jù)賬戶 ID 查找對(duì)應(yīng)的賬戶信息。如果給定的 ID 沒(méi)有找到對(duì)應(yīng)的賬戶,就會(huì)拋出 IllegalArgumentException 異常。

接著,我們會(huì)用新的金額更新檢索到的賬戶信息。最后,使用 CrudRepository 的 save() 方法將更新后的賬戶信息保存到數(shù)據(jù)庫(kù)中。

在這個(gè)看似簡(jiǎn)單的例子中,其實(shí)存在著一些潛在的風(fēng)險(xiǎn)點(diǎn)。比如,我們可能找不到目標(biāo)賬戶,從而導(dǎo)致操作因異常而失敗。又或者,save() 操作在更新轉(zhuǎn)出賬戶時(shí)成功了,但在更新轉(zhuǎn)入賬戶時(shí)卻失敗了。

這些情況都屬于部分失敗,因?yàn)樵谑≈耙呀?jīng)執(zhí)行的操作無(wú)法撤銷。如果我們不使用事務(wù)機(jī)制來(lái)管理這些代碼,部分失敗就很可能會(huì)導(dǎo)致數(shù)據(jù)一致性問(wèn)題。

例如,我們可能從一個(gè)賬戶中移除了資金,但卻沒(méi)有成功將其轉(zhuǎn)移到另一個(gè)賬戶中。

2. 從 @Async 調(diào)用 @Transactional

當(dāng)我們從 @Async 方法中調(diào)用 @Transactional 方法時(shí),Spring 會(huì)發(fā)揮其強(qiáng)大的管理能力,正確地管理事務(wù)并傳播其上下文,從而確保數(shù)據(jù)的一致性。

讓我們來(lái)看一個(gè)具體的例子。假設(shè)我們有一個(gè) transferAsync() 方法,它被 @Async 注解修飾,這意味著它會(huì)在一個(gè)與調(diào)用線程不同的上下文中并行運(yùn)行。在這個(gè)方法中,我們調(diào)用了一個(gè)被 @Transactional 注解修飾的 transfer() 方法來(lái)執(zhí)行關(guān)鍵的業(yè)務(wù)邏輯。

圖片圖片

在這種情況下,Spring 會(huì)將 transferAsync() 線程的上下文正確地傳播給 transfer() 方法。這樣一來(lái),我們就不會(huì)在這個(gè)交互過(guò)程中丟失任何數(shù)據(jù)。

transfer() 方法定義了一組關(guān)鍵的數(shù)據(jù)庫(kù)操作,如果在執(zhí)行過(guò)程中發(fā)生任何失敗,Spring 會(huì)自動(dòng)回滾這些操作。需要注意的是,Spring 只處理 transfer() 方法內(nèi)部的事務(wù),會(huì)將 transfer() 方法體外的所有代碼與事務(wù)隔離開(kāi)來(lái)。因此,只有當(dāng) transfer() 方法內(nèi)部發(fā)生失敗時(shí),Spring 才會(huì)回滾其代碼。

從 @Async 方法中調(diào)用 @Transactional 方法是一種非常巧妙的設(shè)計(jì),它既可以通過(guò)并行執(zhí)行操作來(lái)提高性能,又可以確保特定內(nèi)部操作的數(shù)據(jù)一致性,實(shí)現(xiàn)了性能和數(shù)據(jù)一致性的雙贏。

3. 從 @Transactional 調(diào)用 @Async

Spring 目前使用 ThreadLocal 來(lái)管理當(dāng)前線程的事務(wù),這意味著它不會(huì)在應(yīng)用程序的不同線程之間共享線程上下文。因此,如果 @Transactional 方法調(diào)用 @Async 方法,Spring 不會(huì)將同一事務(wù)的線程上下文傳播給 @Async 方法。

為了更直觀地理解這個(gè)問(wèn)題,我們?cè)?nbsp;transfer() 方法內(nèi)部添加一個(gè)對(duì)異步 printReceipt() 方法的調(diào)用。

圖片圖片

transfer() 方法的邏輯與之前相同,只是增加了調(diào)用 printReceipt() 方法來(lái)打印轉(zhuǎn)賬結(jié)果的操作。由于 printReceipt() 方法被 @Async 注解修飾,Spring 會(huì)在另一個(gè)上下文的不同線程上運(yùn)行其代碼。

這里就存在一個(gè)問(wèn)題,收據(jù)信息的打印依賴于 transfer() 方法的整個(gè)正確執(zhí)行。然而,printReceipt() 方法和 transfer() 方法中保存到數(shù)據(jù)庫(kù)的其余代碼在不同的線程上運(yùn)行,且數(shù)據(jù)不同,這就使得應(yīng)用程序的行為變得不可預(yù)測(cè)。例如,我們可能會(huì)打印一個(gè)在成功保存到數(shù)據(jù)庫(kù)之前的轉(zhuǎn)賬交易結(jié)果。

為了避免這種數(shù)據(jù)一致性問(wèn)題,我們必須避免從 @Transactional 方法中調(diào)用 @Async 方法,因?yàn)樵谶@種情況下不會(huì)發(fā)生線程上下文的傳播。

4. 在類級(jí)別使用 @Transactional

使用 @Transactional 注解定義一個(gè)類時(shí),該類的所有公共方法都會(huì)被納入 Spring 的事務(wù)管理范圍。這意味著該注解會(huì)一次性為所有方法創(chuàng)建事務(wù)。

在類級(jí)別使用 @Transactional 時(shí),可能會(huì)出現(xiàn)同一個(gè)方法同時(shí)使用 @Async 注解的情況。實(shí)際上,我們是在該方法的周圍創(chuàng)建了一個(gè)事務(wù)單元,并且這個(gè)事務(wù)單元會(huì)在與調(diào)用線程不同的線程上運(yùn)行。

圖片圖片

在上面的例子中,transferAsync() 方法既是事務(wù)性的又是異步的。因此,它定義了一個(gè)事務(wù)單元并在不同的線程上運(yùn)行。因此,它可用于事務(wù)管理,但不在與調(diào)用線程相同的上下文中。

因此,如果發(fā)生失敗,transferAsync() 內(nèi)部的代碼會(huì)回滾,因?yàn)樗?nbsp;@Transactional 的。然而,由于該方法也是 @Async 的,Spring 不會(huì)將調(diào)用上下文傳播給它。因此,在失敗的情況下,Spring 不會(huì)回滾 trasnferAsync() 之外的任何代碼,就像我們調(diào)用一系列僅包含事務(wù)的方法時(shí)一樣。因此,這與從 @Transactional 中調(diào)用 @Async 面臨相同的數(shù)據(jù)完整性問(wèn)題。

類級(jí)別的注解對(duì)于編寫(xiě)較少代碼以創(chuàng)建定義一系列完全事務(wù)性方法的類非常有用。

但是,這種混合的事務(wù)性和異步行為在調(diào)試代碼時(shí)可能會(huì)造成混淆。例如,我們期望在發(fā)生失敗時(shí),一系列僅包含事務(wù)的方法調(diào)用中的所有代碼都會(huì)回滾。然而,如果這一系列方法中的某個(gè)方法也是 @Async 的,那么行為就會(huì)出乎意料。

總結(jié)

在本教程中,我們從數(shù)據(jù)完整性的角度學(xué)習(xí)了何時(shí)可以安全地將 @Transactional 和 @Async 注解一起使用。

通常,從 @Async 方法中調(diào)用 @Transactional 方法可以保證數(shù)據(jù)完整性,因?yàn)?Spring 會(huì)正確地傳播相同的上下文。

但是,從 @Transactional 中調(diào)用 @Async 方法時(shí),我們可能會(huì)遇到數(shù)據(jù)完整性問(wèn)題。

責(zé)任編輯:武曉燕 來(lái)源: 碼猿技術(shù)專欄
相關(guān)推薦

2024-07-22 14:09:22

@AsyncJava

2018-03-16 17:25:22

存儲(chǔ)

2025-05-07 00:20:00

@AsyncSpring事務(wù)

2024-07-16 08:36:33

線程池父子任務(wù)微服務(wù)

2024-04-07 00:00:05

事務(wù)Java開(kāi)發(fā)

2022-05-07 10:20:17

truncatedeleteMySQL

2018-07-06 15:04:24

緩存token線程

2021-08-26 10:50:37

MySQLORDER BYIMIT

2025-01-16 16:16:53

2020-04-24 20:05:16

VueAxios前端

2019-01-18 14:57:57

Oracle云計(jì)算AWS

2019-12-20 14:56:50

批量刪除數(shù)據(jù)數(shù)據(jù)刪除

2022-07-06 08:36:34

threadpromise

2023-11-02 07:52:30

Java工具

2021-05-07 07:59:52

WebFluxSpring5系統(tǒng)

2019-10-17 10:12:02

Go語(yǔ)言Java函數(shù)

2024-12-23 08:00:45

2023-05-05 07:39:04

Spring事務(wù)面試

2023-09-27 16:22:51

SpringMySQL原子性

2017-05-18 16:40:18

跨公網(wǎng)架構(gòu)線程
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 久久精品av | 在线看无码的免费网站 | 女人天堂av | 国产丝袜一区二区三区免费视频 | av三级在线观看 | 亚洲国产一区二区三区 | 亚洲美女一区 | 国产色婷婷精品综合在线播放 | 99精品欧美一区二区三区综合在线 | caoporon| 中文字幕亚洲一区二区三区 | 成人黄色电影免费 | 亚洲视频在线观看 | 综合激情av | 国产1区2区| 精品九九九 | 欧美日韩在线综合 | 亚洲精品视频一区 | 午夜一级黄色片 | 欧美成年人 | av成人在线观看 | 日本精品久久久一区二区三区 | 黄色三级在线播放 | 一区二区精品在线 | 日韩影音| 超碰人人爱| 欧美午夜一区 | 国产精品久久久久久妇女6080 | 亚洲成人精品久久 | 国产第二页 | 久久久久网站 | 国产在线不卡 | 国产特级毛片 | 日韩精品一区二区三区视频播放 | 九九亚洲| 91视频网址 | 欧美日韩一区二区三区不卡视频 | 91精品久久久久久久久99蜜臂 | 视频在线一区二区 | 96国产精品久久久久aⅴ四区 | 成在线人视频免费视频 |