從分散式到雲端服務:Google Spanner 成長之路
摘要:距離 Google 開始開發 Spanner 已經 10 年,5 年前 Google 發表了論文,在 Google 雲平臺上增加開放 Spanner 服務,意義不僅僅是服務於 AdWords 和 Google Play,而是希望在雲端更有所為。在這 5 年時間裡,正是由於其他廠商無法複製 Google 的想法,即不能解決大規模叢集下高可用性、水平擴充套件能力、資料強一致性等。本文從 Spanner 技術著手,逐漸引出最近的特大訊息:Google 開放 Spanner 雲端能力(測試版)。
Spanner 技術概括
簡介
Spanner 是 Google 的可擴充套件、多版本支援、全球分散式的同步備份資料庫,領軍人物是 Eric Brewer,他是 CAP 理論的創造者、超級大牛。Spanner 是第一個支援全球規模的分散式資料庫。當資料量或者伺服器數量發生變化時,Spanner 在機器之間自動共享資料,並且 Spanner 在機器之間自動遷移資料(甚至在資料中心之間),用於負載均衡和響應失敗。Spanner 被設計為可以在數百萬臺機器之上橫向擴充套件,覆蓋數百個資料中心、上億條資料。
五年前發表的論文《在 Google 雲平臺上增加開放 Spanner 服務》,描述了 Spanner 資料庫的內部結構是怎麼樣的、包含哪些屬性、各種設計決策的基本原理,也暴露了一種新的不確定性時鐘時間 API。這些 API 和他們的實現對於支援外部一致性和幾個重量級的特徵來說極其重要,這些特徵包括非阻塞式多版本讀(nonblocking reads in the past)、無鎖只讀交易(lock-free read-only transactions)、原子模型變化(atomic schema changes),這些特徵貫穿 Spanner 內部設計。
Spanner 是一個在遍佈全球範圍的資料中心內部穿過多套 Paxos 狀態機器共享資料的資料庫。複製被用於全域性可用性和地理位置;客戶在副本之間自動切換。當資料量或者伺服器數量發生變化時,Spanner 在機器之間自動共享資料,並且 Spanner 在機器之間自動遷移資料(甚至在資料中心之間),用以負載均衡和響應失敗。Spanner 被設計為在幾百萬臺機器之上橫向擴充套件,這些擴充套件穿過了數百個資料中心和萬億行資料。
應用程式可以使用 Spanner 實現高可用性,甚至面對大面積的自然災害,通過地區內部、甚至跨洲的備份資料策略。Spanner 最早的客戶是 F1,它是一個 Google 廣告系統的後臺程式。F1 在美國境內一共有 5 個副本。大多數應用程式在選擇分散式資料庫的時候,首選要求是低延時,然後才是高可用性,只要能夠挺過 1-2 次資料中心故障就可以了。
Spanner 是從類似於 Bigtable 這樣的鍵值對(Key-Value)儲存演變過來的一種時態多版本資料庫。資料被儲存在半關係型資料模型裡,資料通過版本管理,每一個版本自動建立提交時間作為時間戳,老版本的資料服從垃圾回收機制管理。
和 NoSQL 資料庫不同,Spanner 屬於 NewSQL 資料庫。
與其他資料庫對比
我們針對 Spanner、關係型資料庫、NoSQL 資料庫所能提供的功能進行對比,如圖所示。
Spanner Schema 設計
Spanner 不需要每張表必須有一個主鍵列。由於 Bigtable 持續被投訴,所以 Google 在設計 Spanner 時把分散式交易集中化,因為過多的交易容易造成效能瓶頸出現。
在 Spanner 的模式定義語言裡,你可以在表之間使用 INTERIAVE IN 申明表之間的層次關係。在層次關係的最頂層表示一張 Directory 表,其他的下級表示按照字典形式命名排序的。ON DELETE CASCADE 被用於當 Directory 表裡的一行資料被刪除時,相應地一併刪除子表裡的對應資料。建立 Spanner 資料表如圖所示。
讀 / 寫方式
Spanner 提供三種類型的操作:讀 / 寫交易、讀交易和快照讀操作。
單一的寫操作是通過一個讀 / 寫交易執行的,然而一個單一的讀操作,不是一個快照讀,是通過一個讀交易執行的。
一個寫操作執行了一個讀 / 寫交易,在提交交易之前都是快取在客戶端。一個交易裡面的讀操作,不會被寫操作的結果所影響。讀 / 寫交易當中的讀操作使用了 Wound-Wait 方式避免死鎖。客戶端從協調節點獲取讀鎖,然後讀取最新的資料。
全球分散式設計
Spanner 最初的出現就是因為 Google 內部使用的 Bigtable 無法確保跨地區的資料中心強一致性。Spanner 的整體集合被稱為 Universe。一個 Universe 又由幾個 Zone 組成。一個 Zone 意味著一個單元,這個單元可以物理上獨立執行。一個數據中心可能超過 1 個 Zone。如果你想要在不同的服務組記憶體儲資料,你需要在一個數據中心內部建立兩個或者以上的 Zone。
上面這張圖顯示了在一個 Universe 裡面配置的伺服器,一個 Zone 由一個 Zonemaster 和幾千個 Spanserver 組成。Zonemaster 為 Spanserver 分配資料。同時,Spanserver 實際儲存和處理資料。Location Proxy 通過客戶端呼叫,顯示目標資料被儲存在哪個 Spanserver。Universemaster 提供了所有 Zone 的狀態或者除錯資訊,並且 Placement Driver 實際上執行 Zone 之間的資料傳輸,決定是否資料被移除了(由於備份策略改變或者通過與 Spanserver 之間的定期通訊進行負載均衡)。
每一個 spanserver 大約有 10 到 1000 個被叫做 Tablet 的資料結構。Tablet 可以儲存多個對映,字串 (key:string, timestamp:int64) 形式。Spanner 裡的 Tablet 和 BigTable 裡的 Tablet 的差別是,Spanner 儲存一個數據的同時帶了時間戳。這意味著 Spanner 不僅僅是一個簡單的鍵值對儲存,而是帶有多版本特性的資料庫。
Table 的狀態儲存在 Colossus Distributed File System,基於二叉樹檔案形式和 write-ahead log(WAL)。
Spanner 使用 Paxos 狀態機支援 spanservers 之間的資料備份。
一個 spanserver 有交易管理者,用於支援分散式事務。交易管理者在單一 Paxos 組內不會參與交易執行,但是當多個 Paxos 組之間進行交易時它會參與進去,參與人之一會被選舉為協調組長,基於 phase-2 commit 協議執行協調。
目錄是一組連續的鍵,這些鍵使用相同的字首(你可以想象成一個桶)。Directory 是一個數據分配的基本單元。Directory 裡面的所有資料有定義好的備份設定,並且 Paxos 組之間的資料傳輸也是指定的。
一個應用程式可以在一個 universe 內部建立 1 個或多個數據庫,一個數據庫有多張表(沒有上限)。一張表有行和列,比關係型資料庫表多的是有版本資訊。在 Spanner 的模式定義語言裡,你可以在表之間使用 INTERLEAVE IN 申明層次(hierachical)關係。在層次關係的最頂層表示一張 directory 表。根據 directory 表裡定義的鍵,字表命名是根據字典排序的。ON DELETE CASCADE 被用於當 directory 表的一行資料被刪除時,相應地一起刪除子表裡面的資料。
F1
Spanner 的最早的客戶是 F1,它是一個 Google 廣告系統的後臺程式。F1 在美國境內一共有 5 個副本。許多其他的應用程式最有可能的是在一個地理區間內在 3 到 5 個數據中心中間複製資料,但是它們具有相對獨立的失效模式(failure mode)。也就是說,大多數應用程式會首選較低延遲,然後才是高可用性,只要能夠挺過 1 到 2 次的資料中心故障。
Google F1 SQL 資料庫管理系統構建在 Spanner 之上,用於替換 Google 的 MySQL 定製版本。Spanner 使用 Paxos 演算法作為操作的一部分,用於在數百個資料中心之間共享資料。
技術總結
Spanner 提供了類似於關係型資料庫的功能支援和操作方式,每張表都有主鍵、可以管理和刪除級聯表的資料。Spanner 支援 ACID 和 SQL 語句。由於 Spanner 會把上億條資料存放在全球很多資料中心裡,所以當你讀取資料時,Spanner 把讀取請求發到物理上最接近你的資料中心,當你寫入資料時,你會儲存到多個數據中心。如果資料中心整體停止服務,你也可以從副本資料中心環境讀取資料。
釋出 Cloud Spanner 測試版本
2017 年 2 月 14 日(情人節),Google 宣佈 Cloud Spanner 釋出測試版本。這是一個基於雲端的全球分散式關係資料庫服務,支援包括 ACID 交易、SQL 語義,支援水平擴充套件和高可用性。當我們構建一個基於雲端的應用程式時,資料庫管理員和開發人員都需要去選擇使用關係型資料庫或者 NoSQL 資料庫,關係型資料確保交易永續性,NoSQL 資料庫提供了簡單、水平擴充套件和資料分散式。Cloud Spanner 打破了這種非此即彼的選擇方案,提供了集兩個關鍵能力與一體的,完全管理的服務。
Cloud Spanner 與 Google 頗有淵源,早在 2012 年的一份檔案中 Google 就記錄了 Cloud Spanner,並且已在內部使用多年。目前谷歌的雲資料庫服務陣營包括 Google Bigtable(谷歌 2015 年釋出的一個全面管理、高效能、可擴充套件的 NoSQL 資料庫服務)、Google Container Engine(谷歌為解決企業管理大量容器技術編排的繁瑣工作而推出的容器管理服務) 等。
Google 產品經理 Deepti Srivastava 曾在一篇博文中寫道:
Cloud Spanner 通過在熟悉的關係資料庫環境中支援標準工具和語言,簡化了應用程式開發。它是傳統關係資料庫支援執行的工作負載的理想選擇,如庫存管理,金融交易和控制系統以及其它系統。
Cloud Spanner 同 GCP、Cloud SQL、Cloud Datastore、Cloud Bigtable 一起,豐富了我們資料庫服務的能力。
作為一個可控的服務,Cloud Spanner 給 DBA 提供了下列重要福利:
- 讓 DBA 把寶貴的精力專注於業務邏輯上,而不是用於處理各種軟體或硬體問題;
- 使得 DBA 不用執行復雜的分片或者叢集操作,就可以實現對 RDBMS 解決方案的擴充套件;
- DBA 不用把關係資料庫遷移到 NoSQL 資料中,也能獲得資料的水平擴充套件能力;
- DBA 無需複雜的資料備份或失效援備機制,即可維護資料的高可用性,以及具備對資料的災備恢復能力;
- 將安全性與資料層加密,身份驗證,接入管理,日誌稽核等功能進行整合。
Cloud Spanner 並沒有違反 CAP 定理。這些年,我們已經讓 Spanner 打贏了 Google 內部很多場戰鬥,數百個不同的應用程式,PB 級別的資料在全球的資料中心間轉移。在 Google,Spanner 支援每秒數以百萬計次的查詢,執行的應用程式包括 AdWords 和 Google Play。
有了 Cloud Spanner,你可以對資料庫的規模按照需求來擴充套件和縮小,然後你只需要按照使用規模來付費即可。Spanner Cloud 的特色之一就是提供了一個簡潔的收費模式,可通過計算節點使用的小時數,實際儲存消耗(而不是預估儲存消耗)以及外部網路接入等指標來計算費用。
Cloud Spanner 力圖保持應用開發的簡潔性,支援開發者們熟知的關係資料庫環境、工具和語言。因此它對那些通過傳統關係資料庫來的驅動的應用作業(如裝備管理,金融事務,控制系統,以及那些規模快速增長的系統)是非常理想的。Cloud Spanner 同時還資料線了分散式事務,Scheme 和 DDL 宣告,SQL 查詢和 JDBC 驅動等功能,並且支援多種主流語言,如 Java,Go,Python,Node.js 等。
Google Cloud Platform 也將繼續完善 Google Cloud SQL 服務以及 Google Cloud Datastore。與此同時,AWS 和 Microsoft 也並未放慢在雲領域的腳步。AWS 提供與 MySQL 相容的 Aurora 關係資料庫以及關係資料庫服務 (RDS),而 Microsoft Azure 在虛擬機器 (VM) 上提供 Azure SQL 資料庫以及 SQL Server。
全文總結
簡而言之,距離 Google 開始開發 Spanner 已經 10 年,5 年前 Google 發表了論文,在 Google 雲平臺上增加開放 Spanner 服務,意義不僅僅是服務於 AdWords 和 Google Play,而是希望在雲端更有所為。在這 5 年時間裡,正是由於其他廠商無法複製 Google 的想法,即不能解決大規模叢集下高可用性、水平擴充套件能力、資料強一致性等。Cloud Spanner 在做到兼顧優勢的同時,並沒有違反 CAP 理論。這也就是為什麼 Spanner 在雲端開放服務的訊息成為了一個衝擊性的新聞,讓我們拭目以待 Google 的極客精神。
相關技術名詞解釋
NewSQL:這是一種完全不同的資料庫架構。NoSQL 的一個優點是橫向擴充套件能力,缺點是沒有提供強一致性,它們不可以被使用在強一致性環境下。NewSQL 和 NoSQL 一樣具有很強的擴充套件能力,同時也提供了和 RDBMS 一樣的單個節點上的 ACID。NewSQL 術語最早在 2011 年由 Matthew Aslett 創造。HBase 也提供了有限形式的事務(單行事務)。然而,這種有限交易不能完全吻合業務需求。HBase 也是一種 NewSQL。
wound-wait:Spanner 論文中提到了使用“wound-wait”策略防範死鎖。這是一種基於剝奪的方法,當程序 Pi 請求的資源正在被程序 Pj 佔有時,只有當程序 Pi 的時間戳比程序 Pj 的時間戳大時,即 Pi 比 Pj 年輕時,Pi 才能等待。否則 Pj 被 Roll Back,即死亡。只要被 Roll Back 的程序重新啟動,使用原有的時間戳,這兩種方案就能避免死鎖和餓死現象。由於時間戳總是增加的,被 Roll Back 的程序最終將具有最小的時間戳。
CAP 定理:指的是在一個分散式系統中,一致性、可用性、分割槽容錯性,三者不可得兼。CAP 理論是在分散式儲存系統中,最多隻能實現上面的兩點。而由於當前的網路硬體肯定會出現延遲丟包等問題,所以分割槽容忍性是必須實現的。
ACID:在可靠的資料庫管理系統中,事務所應該具有的四個特性,即原子性、一致性、隔離性、永續性。原子性是指事務是一個不可再分割的工作單位,事務中的操作要麼都發生,要麼都不發生。一致性是指在事務開始之前和事務結束以後,資料庫的完整性約束沒有被破壞。這是說資料庫事務不能破壞關係資料的完整性以及業務邏輯上的一致性。多個事務併發訪問時,事務之間是隔離的,一個事務不應該影響其它事務執行效果。永續性,意味著在事務完成以後,該事務所對資料庫所作的更改便持久的儲存在資料庫之中,並不會被回滾。
文章來自微信公眾號:高效開發運維