當資料庫遇到分布式

2022-02-02 11:24:56 字數 3973 閱讀 9324

newsql日漸火熱,無論還是開源的tidb,cockroachdb還是網際網路大廠的spanner,oceanbase都號稱newsql,也就是分布式資料庫。newsql的典型特徵就是,支援sql,支援事務,高效能,低成本,高可靠,強一致,易擴充套件,運維友好等。從newsql的演進來看,所謂newsql,可以簡單理解為nosql+傳統的關係型資料庫的結合,nosql強調分布式(高可用,可擴充套件),關係型資料庫則強調事務,sql。正因為二者的疊加,所以需要把兩個領域的概念整合在一起,本文主要想把分布式資料庫中幾個基本概念講清楚。

資料庫和分布式系統中都有一致性概念,由於很多英文單詞對應的中文都是「一致性」,導致容易產生誤區。資料庫中的acid,c是consistency,這個c主要強調應用邏輯的一致性,比如應用定義的約束,包括外來鍵等。分布式系統的cap以及一致性協議,也稱為一致性。前者主要強調,讀是否能讀到最新,以及併發場景下操作執行的時序關係,主要包括線性一致性(linearizability),順序一致性(sequential consistency),因果一致性(causal consistency)等;後者主要強調「共識」,分布式中的多個節點對某個事情(選主,事務提交)達成一致,常見的共識演算法包括paxos協議,raft協議等。

簡單來說,線性一致性要求,第一,「寫後讀」,這裡寫和讀是兩個操作,如果寫操作在完成之後,讀才開始,

讀要能讀到最新的資料,而且保證以後也能讀操作也都能讀到這個最新的資料。第二,所有操作的時序與真實物理時間一致。相對於「寫後讀」,第二點要求即使不相關的兩個操作,如果執行有先後順序,線性一致性要求最終執行的結果也需要滿足這個先後順序。比如,操作序列(寫a,讀a,寫b,讀b),那麼不僅,讀a,讀b能讀到最新a

值和b值;而且要保證,如果讀b讀到最新值時,讀a一定也能讀到最新值,也就是需要保證執行時序與真實時序相同。第三點,如果兩個操作是併發的(比如讀a沒有結束時,寫b開始了),那麼這個併發時序不確定,但從最終執行的結果來看,要確保所有執行緒(程序,節點)看到的執行序列是一致的。

下圖對線性一致性有詳細的論述,**於[6]

順序一致性(sequential consistency)

相比線性一致性,主要區別在於,對於物理上有先後順序的操作,是否要保證這個時序。具體而言,對於單個執行緒,操作的順序仍然要保留,對於多個執行緒(程序,節點),執行的事件的先後順序與物理時鐘順序不保證。但是要求,從執行結果來看,所有執行緒(程序,節點)看到的執行序列是一樣的。詳細定義**於[6]

​下圖的例子很好的區分了線性一致性和順序一致性。

​對於(a),執行序列write(y,2),read(x,0),write(x,4),read(y,2),結果符合要求,但是從客戶端的角度來看,write(x,4)先於read(x,0)執行,但是read卻沒有讀到最新值。

對於(b),write(y,2)和read(y,2)有先後順序,也是符合「寫後讀」,所以是線性一致性。

對於(c), 有幾種可能:

1).write(x,4),read(y,0),write(y,2),read(x,0),x的寫後讀,不符合要求;

2).write(y,2),read(x,0),write(x,4),read(y,0),y的寫後讀,不符合要求。

所以既不符合線性一致性,也不符合順序一致性。

相對於順序一致性,弱化了不相關操作是否需要保序

對於b),p1和p2 w(x)是沒有先後關係的,因此誰先發生都是可以的。

從p3的視角來看,操作執行的序列是w(x,7),r(x,7),w(x,2),r(x,2),w(x,4);保證了「寫後讀」

從p4的視角來看,操作執行序列是w(x,2),w(x,4),r(x,4),w(x,7),r(x,7);保證了「寫後讀」

但是不同程序看到的執行序列不一樣,所以不符合順序一致性。

無事務併發,事務的執行沒有重疊)。那麼如何實現併發控制來達到可序列化排程。資料庫中對於同一物件的操作可能存在幾類衝突,包括讀寫衝突,寫寫衝突,寫讀衝突等,如果解決了這些衝突,也就實現了可序列化排程。實際上衝突可序列化排程是可序列排程的充分條件,並非必要條件,詳細展開可以看這篇blog,而我們實際的資料庫系統中實現可序列化排程也是解決衝突序列化問題。主要有兩種,一種是基於s2pl(strict 2 phrase locking),事務操作過程中,對讀加讀鎖,對寫加寫鎖,事務提交時,才將鎖釋放,為了避免幻讀,還需要實現間歇鎖等;另外一種,是基於snapshot的ssi隔離級別,這種實現與s2pl的主要區別在於,讀仍然採用快照讀,不加鎖,讀寫不互斥,為了實現可序列化排程,需要收集事務的讀寫操作資訊,並判斷是否事務有相互依賴的情況(衝突成環),如有,則將衝突的事務回滾,實際上是first-commit-win原則,最後導致成環的事務會被回滾。具體可以參考**:serializable isolation for snapshot databases,目前商業資料庫pg和cockroachdb都是實現了ssi隔離級別。而mysql的innodb儲存引擎則是採用了s2pl實現了可序列化隔離級別。

前面分別介紹了分布式系統中的一致性以及資料庫中的可序列化隔離級別,分布式資料庫顯然是分布式系統,也是資料庫系統,那麼是否能做到線性一致性+可序列化,就是所謂的「strong consistency」。這個定義**於jepsen的一篇blog,具體可以看下圖。

​資料庫要實現「線性一致性」,需要保證事務操作按全域性時鐘的先後順序。對於寫而言,通過乙個統一的地方分配時間戳,顯然先後執行的事務分配的時間戳也滿足先後關係。這裡實際上需要乙個統一「全域性時間源」,也就是業內常用的tso(timestamporacle)方案,tso能保證所有事務全域性有序。對於讀而言,讀採用加鎖當前讀,也能保證讀到最新,所以結合s2pl可以兼得可序列化+線性一致性,也就是實現strict serializable。

google spanner**還提到乙個外部一致性的概念,

​spanner通過gps+原子鐘保證了所有事務的寫有序,實現了類似tso的功能,但是避免了tso的單點可用性和效能問題。它提到external consistency相比linearizability,主要是約束了非相關併發事務的提交順序與物理時鐘要保持一致,因為linearizability並不約束併發執行的操作。**中沒有提到spanner如何實現serializable隔離級別,我猜測是類似ssi的實現,那麼仍然做不到strict serializable。

分布式資料庫中的一致性概念有很多,但含義都不太一樣,acid中的一致性主要強調應用邏輯的一致性,需要應用參與保證一致性,cap中的一致性則主要強調多個副本的一致性,寫後讀是否能讀到最新,這裡面就衍生了幾種一致性,包括線性一致性,順序一致性,因果一致性等。資料庫有隔離級別的概念,對於可序列化隔離級別也要求順序,實際上與分布式系統的一致性沒有什麼關係,它更強調隔離,不強調事務執行的順序是否與真實執行先後順序保持一致。因此,資料庫可能實現了可序列化隔離級別,但是並不一定實現了線性一致性,比如基於ssi實現的可序列化就是這類系統。

[1].spanner**

[2].

[3].

[4].spanner儲存層實現

[5].serializable isolation for snapshot databases

[6].《distributed computing,principles, algorithms, and systems》

分布式資料庫

網路選課系統中分布式資料庫設計 何翠雙王巧雲張麗麗 摘要 關鍵字 選課 分布式 資料庫 distributed system of on line course choosing abstract key words course choosing distributed database 隨著學校...

分布式資料庫

1 背景 我們知道資料是乙個公司的命脈,隨著業務越做越大,資料量也會越來越大,計算也會越來越複雜,效能,可靠性,可擴充套件性的需求就會越來越強烈,這個時候乙個集中式的資料庫顯然已經滿足不了需求了。對於技術決策者來說有兩條路可以走,第一 按照現有的大型資料庫的解決方案,比如sql server clu...

分布式資料庫

一 分布式資料庫的出現的場景 網際網路 軟體國產化 o2o 五新 新零售 新製造,新金融 新資源 新技術 等主題接連提出來,並且在各個行業落地,給資料庫帶來了巨大機會,具體包含3個方向 1.遠超單機資料庫容量的資料儲存和訪問峰值 2.實時資料分析檢索 oltp兼顧olap 3.更高階別的容災需求。這...