自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

為 Key-Value 數(shù)據(jù)庫實現(xiàn)MVCC 事務(wù)

存儲 存儲軟件
在本文中我們會討論一下key-value數(shù)據(jù)庫的無鎖事務(wù)操作,這種技術(shù)可以廣泛應(yīng)用于任何一種數(shù)據(jù)庫系統(tǒng)。在GridDynamics中,我們就用這種技術(shù)在Oracle Coherence上實現(xiàn)了一個輕量級的非標(biāo)準(zhǔn)的事務(wù)機(jī)制。

ACID 是軟件領(lǐng)域使用最廣泛的技術(shù)之一,它是關(guān)系數(shù)據(jù)庫的基石,是企業(yè)級中間件不可或缺的部分,但通常通過黑盒的方式提供。但是在許多情況下,這種古老的事務(wù)方式已經(jīng)不能夠適應(yīng)現(xiàn)代大規(guī)模系統(tǒng)和NoSQL數(shù)據(jù)庫的需要了,現(xiàn)代系統(tǒng)要求更高的性能要求,更大的數(shù)據(jù)量,更高的可用性。在這種情況下,傳統(tǒng)的事務(wù)模型被定制的事務(wù)或者半事務(wù)模型所取代,而在這些模型中事務(wù)性并不像以往那樣被看重。

在本文中我們會討論一下key-value數(shù)據(jù)庫的無鎖事務(wù)操作,這種技術(shù)可以廣泛應(yīng)用于任何一種數(shù)據(jù)庫系統(tǒng)。在GridDynamics中,我們就用這種技術(shù)在Oracle Coherence上實現(xiàn)了一個輕量級的非標(biāo)準(zhǔn)的事務(wù)機(jī)制。在***部分我們會通過幾個重要的用例來了解兩種簡單的方法,在第二部分我們會研究更多更通用的方法,比如說PostgreSQL的MVCC實現(xiàn)。

[[233028]]

原子性緩存切換,讀提交隔離

讓我們從一個簡單易于實現(xiàn)的方法開始,這個方法適用于讀遠(yuǎn)多于寫的系統(tǒng)。比如說電子商務(wù)系統(tǒng)中每天要進(jìn)行的數(shù)據(jù)更新,一些管理性操作例如無效貨品的修復(fù)以及緩存更新。

最簡單的例子是把所有數(shù)據(jù)都加載進(jìn)緩存里,然后通過一個代理接口來執(zhí)行諸如 get() 和 put() 這樣的操作。這個接口會與兩個緩存打交道,A和B,按照以下邏輯運行(圖 1):

任何時候只能有一個緩存處于可用狀態(tài),代理接口會把所有的請求路由給它(圖1.1)。

更新數(shù)據(jù)的時候把新數(shù)據(jù)加載到目前不可用的緩存中(圖1.2)。

更新進(jìn)程切換標(biāo)志哪個緩存可用的標(biāo)記(圖1.3),代理接口開始把新的讀請求分發(fā)到新標(biāo)記為可用的緩存。

緩存切換階段的事務(wù)可以依據(jù)不用的持久性和隔離性要求來分別處理。如果允許“不可重復(fù)讀” ,那么切換很簡單,老數(shù)據(jù)會被立刻清理掉。否則,代理接口會維護(hù)一個仍未結(jié)束的事務(wù)列表,并把屬于這個列表中的每一個請求都路由到原來的緩存中。只有當(dāng)列表中的所有事物都提交或者放棄之后老數(shù)據(jù)才會被清空。

Fig.1 Cache Switch

相同的技術(shù)也可用于部分更新。依據(jù)存儲方式的不同也有多種實現(xiàn)方法,我們來看一個有三個緩存簡單例子。這個例子中的框架遇上一個類似,但是代理接口按照以下邏輯運行(圖 2):

用戶請求被路由到主緩存("PRIMARY"緩存)(圖 2.1)

新增數(shù)據(jù)和更新數(shù)據(jù)加載進(jìn)2號緩存(“NEW”緩存),刪除項的key放入3號緩存("DELETE"緩存)(圖2.2)

提交進(jìn)程(特指寫事務(wù))切換全局標(biāo)示,這個標(biāo)示會告訴代理接口先去"NEW"和"DELETE"緩存去查找所請求的數(shù)據(jù),如果在這兩個區(qū)域中沒有發(fā)現(xiàn)再去"PRIMARY"緩存查找(圖2.3)。換句話說,在這一步所有的請求都被改派到了更新過的數(shù)據(jù)中查找。

提交進(jìn)程將 NEW 和 DELETE 區(qū)域的變化傳遞給PRIMARY。也即在PRIMARY緩存區(qū)以非原子的方式更新、增加、刪除數(shù)據(jù)項(圖2.4)。

***,所有的提交進(jìn)程把全局標(biāo)識切換回來,所有的請求仍然路由到 PRIMARY 緩存區(qū)域(圖2.5)。

在第4步,可以把老數(shù)據(jù)拷貝到另一個緩存區(qū),這樣就可以支持回滾操作。即使是全量更新也可以用這種方法。

Fig.2 Partial Cache Switch

從上面的兩個例子我們可以看出,專用于讀的數(shù)據(jù)快照避免了數(shù)據(jù)更新的干擾,大大降低了復(fù)雜性。在一個寫密集型的環(huán)境中就不容易做到這一點了。在下一節(jié)我們會討論一種非常好的方法可以***的解決這個問題。

MVCC 事務(wù),可重復(fù)讀隔離

事物間的隔離可以通過給數(shù)據(jù)項加上版本號來實現(xiàn)。有許多方法能做到這一點,下面我們會介紹一種與PostgreSQL  的事務(wù)處理方法非常相似的辦法。

正如前面所說,每個事務(wù)可以對應(yīng)于一個部分?jǐn)?shù)據(jù)快照。在同一時間,每一個數(shù)據(jù)項都有他自己的生命周期 - 從加入緩存到移出緩存或者被更新(被新版本所取代)。所以可以通過給每條數(shù)據(jù)打兩個時間戳來實現(xiàn)隔離,每個事物通過開始時間(兩個時間戳之一,譯者注)來找出在事務(wù)開始時處于可見狀態(tài)的數(shù)據(jù)。但在實踐中常用一個單調(diào)遞增的計數(shù)來代替時間戳:

  • 新事務(wù)開始的時候:

它會獲得一個全局唯一且單調(diào)遞增的事務(wù)ID ,也叫 XID。

進(jìn)程里保存著所有事務(wù)的XID.

  • 緩存里的每個數(shù)據(jù)項有兩個額外標(biāo)記,xmin 和 xmax。按照以下規(guī)則賦值:

當(dāng)數(shù)據(jù)項被某個事務(wù)建立的時候, xmin 設(shè)置為該事務(wù)的XID ,xmax 無值。

當(dāng)數(shù)據(jù)被某個事務(wù)移除的時候,xmin 不變,xmax 設(shè)置為該事務(wù)的XID。數(shù)據(jù)并沒有真的從緩存中清除,只是被標(biāo)記為已刪除。

當(dāng)數(shù)據(jù)被某個事務(wù)更新的時候,老數(shù)據(jù)仍然保存在緩存里,xmax 被賦值為事務(wù)的XID,同時增加一條新的數(shù)據(jù),新數(shù)據(jù)的 xmin 也賦值為XID 并且xmax 為空。換句話說更新操作等于一次刪除加一次增加。

  • 如果以下兩個條件成立,那么數(shù)據(jù)對于某次事務(wù)是可見的:

xmin 有值并且小于或等于當(dāng)前事務(wù)ID。

xmax 為空,或者等于未提交事務(wù)(放棄的或者還未完成的)的XID ,或者大于當(dāng)前事務(wù)ID。

xmin 和 xmax 可以存儲兩個位標(biāo)記,表明事務(wù)是否放棄或者提交,這樣才能進(jìn)行上面的檢查(xmax 是否等于未提交事務(wù)的ID)。

邏輯如下圖所示:

Fig.3 PostgeSQL-like MVCC

這種方法的缺點是廢棄數(shù)據(jù)的移除有些繁瑣。因為不同事務(wù)看到的數(shù)據(jù)版本不同,決定何時將數(shù)據(jù)標(biāo)為不可見或者移除是比較復(fù)雜的。不過也有兩種以上的方法能夠做到,***種是PostgreSQL中使用的,第二種是Oracle使用的:

所有的版本都存儲在同一個key-value空間中,對版本數(shù)量沒有限制(也即可以儲存任意多的版本,譯者注)。由一個后臺進(jìn)程來回收老版本數(shù)據(jù),這個回收可以按計劃調(diào)度執(zhí)行也可以再讀或者寫的時候觸發(fā)。

主key-value 空間只儲存***的版本,之前的版本儲存在另外的地方,且儲存老版本的空間大小是固定的。 ***的版本會指向之前的版本,但是卻不能夠由此上溯到之前的任意版本, 因為存儲老版本數(shù)據(jù)的區(qū)域大小是固定的, 太早的版本會被移除。如果某個事務(wù)不能夠找到指定版本的數(shù)據(jù)就會失敗。 

責(zé)任編輯:武曉燕 來源: ITPUB
相關(guān)推薦

2016-11-17 11:24:32

數(shù)據(jù)庫大數(shù)據(jù)

2023-03-26 12:43:31

數(shù)據(jù)庫KeyValue

2010-07-19 10:05:56

ibmdw存儲系統(tǒng)

2015-06-16 11:51:17

百度云NoSQLAtlas

2024-04-08 10:11:15

MYSQL數(shù)據(jù)庫事務(wù)

2010-09-07 15:20:58

SQL語句事務(wù)

2010-10-08 09:38:55

Android數(shù)據(jù)庫事

2009-09-24 14:12:22

Hibernate數(shù)據(jù)

2020-10-13 10:32:24

MySQL事務(wù)MVCC

2011-08-17 10:11:34

MySQL數(shù)據(jù)庫MVCC

2012-02-08 09:33:45

TomP2PJava

2025-04-08 06:00:00

2019-08-19 10:24:33

分布式事務(wù)數(shù)據(jù)庫

2024-05-28 00:00:30

Golang數(shù)據(jù)庫

2020-06-17 16:56:36

數(shù)據(jù)庫MySQL跨行事務(wù)

2024-04-17 08:11:01

數(shù)據(jù)庫事務(wù)流程

2017-08-22 17:10:45

數(shù)據(jù)庫MySQL事務(wù)模型

2010-05-31 15:12:44

MySQL數(shù)據(jù)庫

2018-09-06 14:53:39

數(shù)據(jù)庫事務(wù)隔離隔離級別

2024-11-01 05:10:00

點贊
收藏

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