Ignite Transaction

作者介紹:Redfox

原文鏈接:Ignite Transaction

1. Atomicity Mode

Ignite的支持跨cache的transaction,跨cache的transaction時要求不同cache之間的Atomicity Mode是相同的。
Cache的Atomicity Mode通過CacheConfiguration中的atomicityMode進(jìn)行配置,主要支持下面三種Atomicity Mode:

TRANSACTIONAL_SNAPSHOT

  • 支持多個操作的多個key放在一個邏輯操作(事務(wù))中,放在一個邏輯操作中的事務(wù)要么全成功,要么全失敗,支持ACID特性

  • 同時支持K/V事務(wù)和SQL事務(wù),使用MVCC來支持兩種類型的事務(wù)

  • 不支持near cache

TRANSACTIONAL

  • 支持多個操作的多個key放在一個邏輯操作(事務(wù))中,放在一個邏輯操作中的事務(wù)要么全成功,要么全失敗,支持ACID特性

  • 支持K/V事務(wù)

  • 支持near cache

ATOMIC

  • 所有的操作都是原子的,一次同時只執(zhí)行一個操作

  • 因為不用去做事務(wù)鎖,所以性能比TRANSACTIONAL、TRANSACTIONAL_SNAPSHOT要高

  • 批量寫入(例如PutAll、RemoveAll)可能會部分成功部分失敗,這個操作會拋出一個異常,異常中間包含沒有寫入成功的K/V

2. Concurrency & Isolation

Concurrency:Ignite支持樂觀并發(fā)控制模式和悲觀并發(fā)控制模式,選擇什么樣的并發(fā)控制模式?jīng)Q定了在什么時機對entry進(jìn)行加鎖操作。悲觀并發(fā)控制模式是在prepare階段就對事務(wù)所操作的entry進(jìn)行加鎖,樂觀并發(fā)控制模式是在訪問數(shù)據(jù)的時候,就對entry進(jìn)行加鎖。無論選擇哪種并發(fā)控制模式,在事務(wù)commit之前都存在一個時間區(qū)間,在這個區(qū)間內(nèi),事務(wù)所操作的所有entry,都是加鎖狀態(tài)的。

Isolation:隔離級別定義了并發(fā)執(zhí)行的事務(wù),對同時操作的key,是如何看待和如何處理的。Ignite支持READ_COMMITED、REPEATABLE_READ、SERIALIZABLE幾種隔離級別。

所以并發(fā)控制模型和隔離級別是一個事務(wù)的兩個方面,下面是ignite在這兩個方面的支持。

2.1 悲觀事務(wù)

悲觀事務(wù)在事務(wù)執(zhí)行第一條讀取或者寫入(根據(jù)隔離級別來看是第一條讀取還是寫入)的時候,就會對事務(wù)中所有的entry進(jìn)行加鎖,直到事務(wù)commit或者rollback才釋放鎖定。在這個模式下,鎖定首先在primary節(jié)點上進(jìn)行,在prepare階段將鎖定推送到backup節(jié)點上去,悲觀事務(wù)的加鎖順序很重要(避免死鎖)。ignite中會對entry按照約定的順序規(guī)則進(jìn)行加鎖,悲觀事務(wù)下支持的隔離級別如下:

READ_COMMITED
數(shù)據(jù)讀取的時候不進(jìn)行加鎖,也不需要將數(shù)據(jù)讀取到transaction中進(jìn)行緩存,在第一次寫入的時候才對所有的entry加鎖。如果cache配置中允許的話,可以在backup節(jié)點上讀取數(shù)據(jù)。READ_COMMITED可能的問題就是會導(dǎo)致不可重復(fù)讀,即在一個事務(wù)中讀取兩次數(shù)據(jù),可能會結(jié)果不一樣。

REPEATABLE_READ
在第一次讀寫數(shù)據(jù)時,就將數(shù)據(jù)從primary節(jié)點讀取到transaction map中,并且對所有的entry進(jìn)行加鎖。所有在這個事務(wù)中后續(xù)對同一份數(shù)據(jù)的讀取,都可以讀到在這個事務(wù)里面更新的最新數(shù)據(jù),其它并發(fā)事務(wù)不能修改這個事務(wù)里的數(shù)據(jù),所以可以獲得可重復(fù)讀。

SERIALIZABLE
和REPEATABLE_READ的工作方式相同。

悲觀事務(wù)下的注意點

性能:因為悲觀事務(wù)需要對所有的entry提前加鎖,而且加鎖是要按照一定的順序控制的。所以,類似于putAll這種操作,如果將順序相同的key放到一個part上進(jìn)行操作,可能會減少在客戶端與服務(wù)端之間加鎖的鎖定往來次數(shù);

Long Transaction:因為在悲觀事務(wù)下,我們不能修改集群的topology,要盡量減少時間比較長的悲觀事務(wù);

讀取的一致性:只有在REPEATABLE_READ和SERIALIZABLE的隔離級別下,才能保證完整的讀取一致性,通過讀鎖避免事務(wù)在過程中更新。

2.2 樂觀事務(wù)

樂觀事務(wù)在兩階段提交的prepare階段才在primary節(jié)點上對entry進(jìn)行加鎖,加鎖之后提交到backup節(jié)點上,在commit階段釋放所擁有的鎖。

READ_COMMITED
在cache中的數(shù)據(jù)修改是在發(fā)起節(jié)點上先收集所有的更改,然后在事務(wù)commit階段進(jìn)行應(yīng)用,數(shù)據(jù)讀取的時候不進(jìn)行加鎖,也不需要將數(shù)據(jù)讀取到transaction中進(jìn)行緩存。如果cache配置中允許的話,可以在backup節(jié)點上讀取數(shù)據(jù),READ_COMMITED可能的問題就是會導(dǎo)致不可重復(fù)讀,即在一個事務(wù)中讀取兩次數(shù)據(jù),可能會結(jié)果不一樣。

REPEATABLE_READ
和READ_COMMITED的實現(xiàn)方式相同,區(qū)別在于REPEATABLE_READ會把所有的讀取過來的數(shù)據(jù)在發(fā)起節(jié)點上進(jìn)行緩存,這樣所有后續(xù)這個事務(wù)操作的讀取,都可以確保是local的。

SERIALIZABLE
在第一次讀取某個entry的時候,保存這個entry的版本號。如果在事務(wù)commit的時候,發(fā)現(xiàn)這個事務(wù)操作的所有entry存在一個entry的版本號和集群當(dāng)前最新的entry版本號不相同,則這個事務(wù)失敗,并對這個事務(wù)的修改操作進(jìn)行回滾,用戶需要處理這個異常,并且重試這個事務(wù)。這個中間需要特別強調(diào)的是即使這個事務(wù)只有讀操作,沒有寫操作,這個事務(wù)也可能失?。僭O(shè)后面讀取的數(shù)據(jù)和事務(wù)剛開始時的數(shù)據(jù)不相同)。

樂觀事務(wù)下的注意點

SERIALIZABLE下的重試:因為樂觀事務(wù)是在操作過程中發(fā)現(xiàn)不能操作時,返回和拋出異常。所以我們需要捕獲這種異常,然后進(jìn)行重試,可能導(dǎo)致多個樂觀事務(wù)循環(huán)重試的狀態(tài),所以我們在加鎖時,也要考慮對entry加鎖的順序,降低循環(huán)重試的可能性;

讀取一致性:只有在SERIALIZABLE的情況下,才能保證讀取的一致性。但是即使在SERIALIZABLE的隔離級別下,在COMMIT之前,都可能發(fā)生部分讀的現(xiàn)象,所以一定需要去捕獲拋出的異常,以確保讀取是一致的。

3. MVCC

只有TRANSACTIONAL_SNAPSHOT的原子模式,才支持MVCC特征,這個模式同時支持SQL事務(wù)和K/V事務(wù),這兩種類型的事務(wù)都支持MVCC。

MVCC是數(shù)據(jù)被多個用戶并發(fā)訪問時候,控制數(shù)據(jù)一致性的方法。每個事務(wù)在啟動時獲得數(shù)據(jù)的一致性快照,這個事務(wù)后續(xù)的操作只能看到和修改這個快照內(nèi)的數(shù)據(jù)。當(dāng)事務(wù)更新一個entry時,它需要確保這個entry沒有被其它事務(wù)更新,然后創(chuàng)建這個entry的一個新的版本。這個新版本只有在這個事務(wù)commit之后才能被其它事務(wù)可見,如果這個entry被更新了,那么這個事務(wù)就會失敗。Snapshot并不是物理的,而是邏輯的。它是由集群中的某個節(jié)點進(jìn)行管理這些活動事務(wù)(MVCC-coordinator),這個節(jié)點追蹤所有的活動事務(wù),并且在每個事務(wù)結(jié)束時,都會通知到該節(jié)點。所有打開MVCC的cache操作,都需要從這個節(jié)點上獲得快照數(shù)據(jù)。

目前TRANSACTIONAL_SNAPSHOT只支持悲觀事務(wù)和REPEATABLE_READ隔離級別。

并發(fā)更新

當(dāng)在一個事務(wù)里面(事務(wù)A),先讀取一個entry,再更新這個entry過程中,可能存在另外一個事務(wù)在兩個操作中間將這個entry更新的情況發(fā)生,如果這種情況發(fā)生,那么事務(wù)A會被置為“rollback only”(只允許回滾)的狀態(tài),ignite會拋出異常和設(shè)置SQL的狀態(tài)碼,讓用戶來處理這種狀態(tài),通常這個事務(wù)就需要重試。

限制

跨cache事務(wù)
在同一個事務(wù)里面要求所有的cache都設(shè)置為TRANSACTIONAL_SNAPSHOT模式,因此,如果需要在一個SQL事務(wù)中操作多個table,那么所有的table創(chuàng)建時,也要配置為TRANSACTIONAL_SNAPSHOT模式

嵌套事務(wù)
Ignite支持3種方案來處理嵌套事務(wù),方案在JDBC、ODBC的連接參數(shù)中配置。

ERROR方案:當(dāng)碰到嵌套事務(wù),則拋出錯誤,同時外面的事務(wù)進(jìn)行回滾,默認(rèn)采用這種方案;

COMMIT方案:外圍事務(wù)進(jìn)行提交,嵌套事務(wù)在碰到COMMIT語句時進(jìn)行提交,外圍事務(wù)剩下的語句采用隱含事務(wù)模式;

IGNORE: 嵌套事務(wù)的BEGIN語句被忽略,嵌套事務(wù)中的語句被和外圍事務(wù)一樣執(zhí)行,碰到COMMIT之后,進(jìn)行事務(wù)提交,外圍事務(wù)剩余的語句采用隱含事務(wù)模式。

持續(xù)查詢
如果有其它操作在更新數(shù)據(jù),那么持續(xù)查詢獲得的結(jié)果可能是過期的數(shù)據(jù),因為更新數(shù)據(jù)需要時間通知到MVCC-coordinator節(jié)點上;

一個事務(wù)同時更新的記錄數(shù)會被限制,因為可能造成內(nèi)存泄漏,默認(rèn)限制為20000條;

MVCC模式不支持:near cache、超時策略、事件通知、cache解析器、第三方持久化、堆內(nèi)cache。

4. Two Phase Commit

1.png

2.png

兩階段提交

在分布式的ignite中,一個事務(wù)中的操作可能牽涉到修改多個partition上的數(shù)據(jù),一個partition里面也存在主節(jié)點和備份節(jié)點,要保持一個事務(wù)中對所有節(jié)點的數(shù)據(jù)修改是一致的。ignite采用兩階段提交的方案來進(jìn)行事務(wù)操作,兩階段提交事務(wù)中存在3個角色:
事務(wù)協(xié)調(diào)者(Transaction Coordinator):事務(wù)發(fā)起節(jié)點,它來控制事務(wù)的兩階段提交過程。
主節(jié)點(Primary Partition):ignite中某個partition的主節(jié)點,數(shù)據(jù)讀寫操作的主要對象。
備份節(jié)點(Backup Partition):ignite中某個partition數(shù)據(jù)備份的所在節(jié)點。

5. Near Node & Remote Node

3.png

在ignite中,Transactional coordinator也被稱為Near Node。Near Node控制整個事務(wù)操作的全部流程,包括發(fā)起事務(wù)、跟蹤事務(wù)狀態(tài)、發(fā)起prepare、發(fā)起commit以及等待事務(wù)完成。

Near Node通常是也是集群的client節(jié)點。

6. Transaction Lifecycle

4.png

在ignite中,事務(wù)由tx.start()發(fā)起,然后在Near Node上創(chuàng)建Transaction的上下文環(huán)境,同時在Near Node上還要做以下事情:
1)為Transaction分配一個事務(wù)ID;
2)記錄Transaction開始的時間;
3)記錄當(dāng)前topology的version、狀態(tài)和信息。

將Transaction設(shè)置為active狀態(tài),然后執(zhí)行讀寫操作,再執(zhí)行Commit操作,完成事務(wù)。Transaction commit之后,開始執(zhí)行兩階段提交,在prepare階段,primary完成時需要做做以下事情:
1)檢查保存在Transaction上下文中的topology version和當(dāng)前的topology version是否相同;
2)獲得所有的鎖;
3)創(chuàng)建一個DHT上下文,保存所有的數(shù)據(jù);
4)等待或者跳過備份節(jié)點完成prepare;
5)Near Node發(fā)起執(zhí)行commit操作;
6)等待所有節(jié)點完成commit操作。

7. Pessimistic & READ_COMMITED

5.png

在這種組合模式下,讀取數(shù)據(jù)(例如get、getAll等操作),是不會對entry進(jìn)行加鎖的。所以,可能存在剛開始讀到的某個entry的數(shù)據(jù),和事務(wù)完成(commit)時讀到的某個entry的數(shù)據(jù)是不相同的。

在收到對某個entry的修改操作時,會對這個entry進(jìn)行鎖定操作。當(dāng)發(fā)起commit之前,事務(wù)已經(jīng)完成對所有該事務(wù)需要修改的數(shù)據(jù)的鎖定,commit時,才會對primary或者backup上的二數(shù)據(jù)發(fā)起真正的修改操作。

鎖的釋放只有在整個事務(wù)完成之后才進(jìn)行釋放。

8. Pessimistic & (SERIALIZABLE | REPEATABLE_READ)

6.png

在這兩種組合模式下,Near Node發(fā)現(xiàn)讀取數(shù)據(jù)(例如get、getAll等操作)時,就會對讀取的數(shù)據(jù)進(jìn)行加鎖操作,同樣的數(shù)據(jù)修改操作也會對讀取的數(shù)據(jù)進(jìn)行加鎖操作。

鎖的釋放只有在整個事務(wù)完成之后才進(jìn)行釋放。

9. Optimistic & (READ_COMMITED|REPEATABLE_READ)

7.png

在這兩種并發(fā)控制組合模式下,數(shù)據(jù)鎖定在prepare階段才會發(fā)生(事務(wù)的commit,兩階段提交的prepare),相對于悲觀并發(fā)控制模式(Near Node上發(fā)現(xiàn)有讀寫即進(jìn)行鎖定)來說,延后了對entry的鎖定時間。在prepare階段,不會比較entry的版本號。

10. Optimistic & SERIALIZABLE

8.png

在這兩種并發(fā)控制組合模式下,數(shù)據(jù)鎖定在prepare階段才會發(fā)生(事務(wù)的commit,兩階段提交的prepare),相對于悲觀并發(fā)控制模式(Near Node上發(fā)現(xiàn)有讀寫即進(jìn)行鎖定)來說,延后了對entry的鎖定時間。在prepare階段,會比較entry的版本號,與事務(wù)剛開始時的entry版本號。如果在prepare階段發(fā)現(xiàn)版本號與事務(wù)剛開始時的版本號不相同,那么在prepare階段就失敗。

11. Lock Timeout

9.png

Ignite允許設(shè)置一個事務(wù)的超時時間,在這種設(shè)定模式下,當(dāng)事務(wù)的執(zhí)行事件超過約定的超時時間時,事務(wù)執(zhí)行失敗,需要進(jìn)行rollback

悲觀并發(fā)控制模式下:每次對entry進(jìn)行鎖定,都會比較事務(wù)執(zhí)行是否超時

樂觀并發(fā)控制模式下:只有在prepare階段進(jìn)行鎖定時,才比較事務(wù)執(zhí)行是否超時

所有參與事務(wù)的節(jié)點都會檢查超時。如果超時,那么會在事務(wù)中設(shè)計一個標(biāo)記,以方便NearNode執(zhí)行事務(wù)撤銷(回滾操作)

12. Backup Node Failure

10.png

如果一個backup節(jié)點損壞,那么事務(wù)仍舊會在剩余的節(jié)點上完成執(zhí)行,不會對當(dāng)前事務(wù)的執(zhí)行產(chǎn)生任何影響。

在事務(wù)執(zhí)行完后,會為這個partition選擇一個新的backup節(jié)點。

13. Primary Node Failure On Prepare

11.png

如果primary節(jié)點在prepare階段失效,那么系統(tǒng)會拋出一個異常給到客戶端,客戶端再將異常給到應(yīng)用程序,由應(yīng)用程序來決定是重新執(zhí)行該事務(wù)還是做其它工作。

14. Primary Node Failure On Commit

12.png

如果primary節(jié)點在prepare節(jié)點完成之后失效,那么Near Node會等待backup節(jié)點發(fā)送過來的消息。

Backup節(jié)點發(fā)現(xiàn)primary節(jié)點失效情況下,會發(fā)送消息給到NearNode節(jié)點。如果backup已經(jīng)完成了這個事務(wù)需要完成的所有修改操作,則Near Node會繼續(xù)完成這個事務(wù)。

同時topology開始發(fā)生改變,并選擇一個新的primary來代替失效的primary。

15. Coordinator(Near Node) Failure

13.png

如果Near Node失效,那么處理過程會比較復(fù)雜,因為系統(tǒng)中可能有的節(jié)點已經(jīng)完成了commit,有的節(jié)點還沒有完成commit,而且系統(tǒng)中的transaction的狀態(tài)目前是沒有保存的。

系統(tǒng)中的primary節(jié)點互相交換信息,只要有一個primary節(jié)點沒有完成commit,則觸發(fā)對這個transaction的回滾操作,參與這個事務(wù)的所有節(jié)點進(jìn)行回滾。

MemFireDB,帶你體驗不一樣的云端飛翔。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容