Spanner 總結
說明:本文為論文 《Spanner: Google’s Globally-Distributed Database》 的個人理解,難免有理解不到位之處,歡迎交流與指正 。
論文地址:Spanner Paper
0. 簡介
Spanner 是由 Google 設計和研發的一款分散式資料庫。它將資料分佈在全球範圍內,並支援外部一致性的分散式事務。對於讀寫事務,它使用基於 Paxos 複製容錯的 2PC ;對於只讀事務,它不使用鎖機制,且允許從本地副本執行讀操作,從而提高了只讀事務處理效率。
1. 結構
1.1 Spanner 伺服器組織
-
一個 Spanner 部署稱為一個 universe
-
Spanner 被組織成許多個 zone 的集合
-
zone 是管理部署的基本單元,當新的資料中心加入服務、或者老的資料中心被關閉時,zone 可以被加入到一個執行的系統中,或從中移除。zone 也是物理隔離的單元,在一個資料中心中可能有一個或多個 zone(當屬於不同應用的資料必須被分割槽儲存到同一資料中心的不同伺服器集合中時,一個資料中心就會有多個 zone)。
-
一個 zone 包含一個 zonemaster 和多個 spanserver
-
zonemaster 把資料分配給 spanserver ,spanserver 把資料提供給客戶端
-
客戶端使用每個 zone 上面的 location proxy 來定位可以為自己提供資料的 spanserver
-
universemaster 主要是一個控制檯,它顯示了關於 zone 的各種狀態資訊,可用於相互之間的除錯
-
placement driver 會週期性地與 spanserver 進行互動,來發現那些需要被轉移的資料(或是為了滿足新的副本約束條件、或是為了進行負載均衡)
1.2 SpanServer 構成
- 在底部,每個 spanserver 負載管理100-1000個稱為 tablet 的資料結構的例項, tablet 實現對映:
(key:string, timestamp:int64)->string
- tablet 的狀態會被儲存到 Colossus 分散式檔案系統中
- 為了支援複製,每個 spanserver 會在每個 tablet 上面實現一個單個的 Paxos 狀態機,每個狀態機都會在相應的 tablet 中儲存自己的後設資料和日誌
- 副本的集合被稱為 Paxos Group ,即一個資料分片(shard)對應一個 Paxos Group
- 寫操作要從 Paxos leader 開始執行,讀操作可以從足夠新的副本中直接執行
- 對於每個是 leader 的副本而言,每個 spanserver 會實現一個 lock table 來實現併發控制
- 對於每個是 ledaer 的副本而言,每個 spanserver 會實現一個 transaction manager 來支援分散式事務。Paxos Group 中的 leader 為 participant leader,其他副本為 participant slave ;如果一個事務包含了多個 Paxos Group ,其中一個 Paxos Group 會被選為 coordinator ,該組 leader 為 coordinator leader ,該組其他副本為 coordinator slaves (這些設定是為了支援 two phase commit)。
1.3 目錄
Spanner 支援 目錄,它是包含公共字首的連續鍵的集合。對目錄的支援,可以讓應用通過選擇合適的鍵來控制資料的區域性性。
一個目錄是資料放置的基本單元,屬於一個目錄的所有資料都具有相同的副本配置。當資料在不同的 Paxos Group 之間移動時,會一個目錄一個目錄地轉移。
2. 分散式事務
2.1 讀寫事務
讀寫事務的提交,採用 基於Paxos的兩階段提交 (2PC) 。
以下述事務為例:
BEGIN:
x = x + 1
y = y - 1
END
上圖中一個黃色矩形框為一個 Data Shard 的 Paxos Group ,每個綠圈為一個副本,儲存在不同的 Data Center 。黑色矩形框中的副本為各 Paxos Group 中的 leader 。
上述讀寫事務的執行過程為(過程與圖中序號對應):
- client 為每個事務設定一個事務 ID (TID)
- client 傳送讀操作給到 X 和 Y 所在 Paxos Group 的 leader。讀操作執行前要先獲得對應記錄的鎖,鎖由 lock table 提供
- 兩個 leader 返回 X 和 Y 的當前值給 client
- 提交前,先選擇一個 Paxos Group 作為2PC 的 transaction coordinator (TC) (圖中紅框即為 TC leader),其餘 Paxos Group 為 transaction participant (TP)。接著,client 傳送寫操作給兩個 Paxos Group 的 leader
- 每個 leader 獲取對應記錄的鎖,通過 Paxos 在 Paxos Group 中記錄
PREPARE
- 如果記錄好
PREPARE
,各 leader 回覆 TCYES
;若出現故障,恢復 TCNO
- TC 接收到所有 TP leader 的回覆之後,決定是提交還是中斷。將決定通過 Paxos 記錄在本 Paxos Group 的 log 中,傳送
COMMIT
通知給所有 TP leader - 每個 TP leader 通過 Paxos 將 TC 的決定記錄在 log 中,之後釋放佔用的鎖
2.2 只讀事務
只讀事務可能包含多個讀操作,讀取資料可能位於多個 Paxos Group ,但不包含寫操作。
因為只讀事務佔比比較大,所以希望只讀操作執行更快。
對於只讀事務,Spanner 進行了兩個方面的優化:允許從本地副本讀取 和 不使用鎖、2PC、事務管理器 。
2.2.1 允許從本地副本讀取
Spanner 允許 client 從本地副本讀取資料,這樣就避免了很多 Paxos 以及 data center 之間的通訊,可以加快只讀事務的處理速度。
但是本地副本可能不是最新的(由於 Paxos 的 majority 機制),為解決這個問題,使用 safe time:
- 每個副本都會跟蹤記錄一個值,稱為 safe time (\(t_{safe}\)),它是一個副本最近更新後的最大時間戳
- 如果一個讀操作的時間戳是 \(t\) ,當滿足 \(t<=t_{safe}\) 時,這個副本就可以被這個讀操作讀取
2.2.2 不使用鎖、2PC和事務管理器
Spanner 支援不加鎖的只讀事務,這一特性同樣避免了很多 Paxos 以及 data center 之間的通訊,並且不會減慢讀寫事務的處理。
對於不加鎖的只讀事務,為保證正確性,必須滿足:
- 可序列化:雖然多個事務會併發執行,但是執行結果等同於它們按照一定順序逐一執行的結果
- 外部一致性:如果 T1 在 T2 開始前提交,則 T2 必須看到 T1 寫操作的結果。
保證正確性的方法是採用 快照隔離 (Snapshot Isolation):
- 首先同步所有伺服器的時鐘
- 為每一個事務設定一個時間戳
- 讀寫事務:以提交開始時間作為時間戳
- 只讀事務:以事務開始時間作為時間戳
- 事務併發執行的效果與以時間戳順序逐一執行的效果相同
- 每個副本對於每條記錄都儲存多個時間戳版本,所有讀寫事務的寫操作都是相同的時間戳
- 只讀事務能看到本事務時間戳之前的資料版本
3. TrueTime
由上述內容可以看到,時間戳在 Spanner 中起到了一個很重要的作用。但是如果不同伺服器上的時鐘不同步,則可能導致一些問題:
- 如果一個只讀事務的時間戳過大,會導致它的時間戳大於副本的 safe time ,讀操作就會阻塞
- 如果一個只讀事務的時間戳過小,會漏讀一些在該事務準確時間戳之前提交的資料版本(即讀到的資料是過期的),這樣違背了外部一致性
為進行時間同步,Spanner 在每個 data center 設定一些 time master server 。每個 time master 含有一個 GPS receiver 或一個 atomic clock 。其他 server 會從幾個 time master server 中收集投票,獲得時間參考值,從而減少誤差。但是由於網路延遲原因,得到的時間也會有一定幅度偏移(時間不確定性問題)。
針對時間不確定性問題,Spanner 提供了一個 TrueTime API ,它將時間顯示錶達為 TTinterval ,它是一個時間區間,具有有界限的時間不確定性,保證了當前準確時間在這個區間裡。TTinterval 的端點是 TTstamp 型別。API 提供了三個方法:
為保證 外部一致性 ,Spanner 設定了兩條規則:
- Start rule:設事務時間戳為
TT.now().lastest
。對於讀寫事務,TT
為開始提交的時間戳;對於只讀事務,TT
為事務開始時間。 - Commit wait:對於讀寫事務,延遲到
TS < TS.now().earliest
時再提交,保證事務時間戳TS
已經完全過去。
6. 特點
- 資料分片儲存在跨越全球的 Paxos 狀態機上,通過併發訪問來提高吞吐量
- Spanner 提供了讀和寫操作的外部一致性,以及在一個時間標準下的全球一致性的讀操作
- 隨著資料變化和伺服器變化,Spanner 可以自動對資料進行重新分片,以進行負載均衡和失敗處理
- 應用可以對資料的副本進行控制,如指定哪些資料中心包含哪些資料
- Spanner 可以為事務分配全球範圍內有意義的提交時間戳,這些時間戳反映事務序列化的順序,用以滿足外部一致性的要求
- 提出了 TrueTime API ,Spanner 時間戳的保證就是取決於這個 API 的界限
- 只讀事務不採用鎖機制,且可以從最新副本上直接讀取資料。由於只讀事務佔比大,因此顯著提升了事務處理效率
5. 和 Aurora 的比較
Spanner | Aurora | |
---|---|---|
架構 | Shared Nothing | Shared Disk |
可用性 | Paxos-based | Quorum-based |
寫擴充套件 | T | F |
分庫分表透明性 | T | F |
分散式事務 | T | F |
MySQL/Postgres相容性 | F | T |
Aurora:主要用於雲上業務,相容 MySQL/PostgresSQL。通過共享儲存方案避免了二階段提交、分散式事務等複雜的實現,因此開發週期較短。
Spanner:是一種重新設計的資料庫,基於 Paxos 的強同步、對分散式事務的支援以及利用 TrueTime 機制實現的全域性一致性讀都是比較強大的功能。但是對 SQL 的相容性不夠好。