在單體資料庫時代,資料庫本身就支援acid事務,開發人員甚至只要在方法上加乙個@transactional註解就可以搞定事務了,非常簡單。但是到了分庫分表和分布式資料庫時代,傳統資料庫的acid屬性只能在單節點上起作用,全域性事務需要乙個全域性的事務管理器來維護,複雜性很高。
而在分布式事務領域,全域性事務使用的最多的指導方案就是2pc,也叫兩階段提交,但是2pc也有一些問題,今天我們就來看看分布式資料庫是怎麼對這些缺陷做優化的。
兩階段提交協議主要有2種,一種是應用層的tcc,比如阿里巴巴的seata就實現了tcc模式,這種模式的特點是每個服務都需要提供try/confirm/cancel這3個實現,這3個實現需要在業務**中實現,對業務侵入高。
今天我分享的是面向資源的2pc協議,最早由jim gray提出,整個事務分為2個階段,prepare階段和commit階段,這2個階段由協調節點和db資源管理器協作完成。
這裡我們還是以經典的電商系統為例,整個系統分為訂單、賬戶和庫存3個服務,我們收到客戶的購買請求後,協調節點需要協調訂單服務生成訂單,賬戶服務扣減商品款,庫存服務扣減商品庫存,假如這3個服務的資料庫在不同切片上,這個協調過程具體如下:
1.prepare階段
協調節點向所有服務傳送prepare請求,每個服務收到prepare請求後會嘗試執行本地事務,但不會真正提交本地事務。這個嘗試執行的過程會檢查到是否具備執行事務的條件,比如資源是否被鎖定等,當所有服務都嘗試執行成功後會給協調節點返回乙個yes,如下圖:
2.commit/rollback階段
如果prepare階段所有服務有返回了yes,那麼協調節點就會通知各個服務執行commit操作,這時各個服務就會真正的提交本地事務。如下圖:
如果prepare階段有服務返回了no,協調節點就需要通知所有服務進行本地事務回滾。
上面我們簡單地分析了2pc協議的執行過程,那麼2pc有什麼問題呢?
1.效能問題
本地事務在prepare階段鎖定資源,比如賬戶服務要扣減xiaoming這個賬戶的金額100元,那必須把xiaoming這個賬戶先鎖定。這樣如果有其他事務也要修改xiaoming這個賬戶,就必須等待前面的事務完成。這樣就造成了延遲和效能下降。
2.協調節點單點故障
協調節點是單節點的,如果發生故障,整個事務會一直阻塞。比如第乙個階段prepare成功了,但是第二個階段協調節點發出commit指令之前宕機了,所有服務的資料資源處於鎖定狀態,後面的事務只能等待。
3.資料不一致
如果第一階段prepare成功了,但是第二階段commit的時候,如果協調節點通知庫存服務失敗了,這樣就相當於生成了訂單,扣減了賬戶,但是沒有扣減庫存。這導致了資料的不一致。
percolator模型來自於google**,網上有好多翻譯版的:
《large-scale incremental processing using distributed transactions and notifications》
percolator的前提是本地事務的資料庫支援多版本併發控制協議,也就是mvcc。現在主流資料庫比如mysql、oracle都是支援的。
a)初始階段
還是看上面我們提到的經典電商案例,初始階段,我們假設訂單數量是0,賬戶服務是1000,庫存服務是100,客戶下了1個訂單後,訂單服務增加1個訂單,賬戶服務扣除金額100,庫存服務扣除商品數量1。各個切片的初始資料如下表:
":"前面的是時間戳或者資料版本,後面是資料值。這3張表中,第一條記錄不儲存真正的資料,而是儲存了指向真正資料的指標,比如訂單表中,6這個版本的資料指向了5個版本的資料,訂單數量是0。
b)prepare階段
在prepare階段,協調節點向每個服務傳送了prepare命令,這3張表分別進入了prepare階段。在prepare階段,percolator定義了主鎖的概念,每個分布式事務只能有乙個服務獲得主鎖,比如本案例的訂單服務,其他服務的鎖指向這個主鎖的指標,如下表:
prepare階段,每個服務會寫日誌,並且根據時間戳記錄事務的私有版本,這樣其他事務就不能操作這三條資料了。
c)commit階段
在commit階段,協調節點只需要跟訂單服務通訊,因為訂單服務擁有primary lock,也就是說協調節點只跟擁有primary lock的切片通訊。這時資料如下表:
這時我們注意到除了order服務的鎖沒有了,而且增加了版本8指向版本7,說明訂單服務已經沒有私有版本了,但是賬戶服務和庫存服務的私有版本還在。percolator的獨特之處就是在這裡,它會啟動非同步執行緒來更新賬戶服務和庫存服務。最終資料如下表:
因為協調節點只需要跟獲取primary lock的切片進行通訊,要麼成功要麼失敗這樣就避免了commit時節點不能全部成功導致的資料不一致問題。
而prepare節點記錄了日誌,如果某個切片commit失敗,可以根據日誌進行再次commit,這樣就保證了資料最終一致。
如果協調節點宕機了,非同步執行緒可以做資源的釋放工作,避免了因單點故障通訊失敗造成的資源不能釋放。
這裡我們要注意2點:
2pc協議由3個問題,效能問題、單點故障和資料不一致。
percolator模型簡化了協調節點和切片的通訊流程,讓協調節點只跟其中乙個primary切片通訊,一方面,減少了通訊開銷,另一方面,避免了因為單點故障,commit階段部分節點通訊失敗導致的資料不一致問題。
percolator在prepare階段記錄了日誌,這樣即使協調節點故障了,恢復後也可以根據日誌來做事務恢復。
percolator使用非同步執行緒來做資源的釋放工作,這樣即使協調節點故障了,也不用擔心資源得不到釋放。
知名的newsql資料庫tidb就是參照percolator模型來對2pc協議進行優化的。
但是我們要知道,2pc的效能問題還是存在的,好在主流的分布式資料庫都做了優化,效能損耗只會越來越小。
聊聊主流的分布式資料庫
單體資料庫時代,隨著系統交易量的不斷上公升,資料庫讀寫效能出現了嚴重下降。我們可以借助分庫分表中介軟體,比如mycat shardingjdbc來實現分庫分表,緩解單庫的讀寫效能。但是分庫分表中介軟體並不支援事務,如果要保證資料一致性,就需要借助於分布式事務中介軟體,比如阿里巴巴的seata。後來分...
分布式資料庫
網路選課系統中分布式資料庫設計 何翠雙王巧雲張麗麗 摘要 關鍵字 選課 分布式 資料庫 distributed system of on line course choosing abstract key words course choosing distributed database 隨著學校...
分布式資料庫
1 背景 我們知道資料是乙個公司的命脈,隨著業務越做越大,資料量也會越來越大,計算也會越來越複雜,效能,可靠性,可擴充套件性的需求就會越來越強烈,這個時候乙個集中式的資料庫顯然已經滿足不了需求了。對於技術決策者來說有兩條路可以走,第一 按照現有的大型資料庫的解決方案,比如sql server clu...