天天看點

傳世的關系模型,巧奪天工的分布式資料庫設計Hadoop生态的分布式資料庫分布式環境下資料庫的一緻性傳世的關系模型

Hadoop生态的分布式資料庫

1. 什麼是分布式資料庫?

從狹義的了解就是分布式關系型資料庫,主要特指目前熱門的NewSQL。

從廣義的了解,分庫分表的傳統關系型資料庫,傳統關系型資料庫叢集,關系型資料庫的主從架構,分布式KV資料庫(例如:HBase),分布式文檔資料庫(例如:MongoDB),分布式關系資料庫(例如:TiDB)等,統稱為分布式資料庫。

本文主要講Google一脈相承的Hadoop生态下的分布式資料庫架構設計,以及傳統RDBMS與NoSQL的分布式環境下的一緻性對比。

2. Hadoop HDFS的資料存儲模型

最早Google發明了GFS分布式檔案系統,之後對應的開源項目就是鼎鼎大名的Hadoop HDFS。

GFS/HDFS的特點表現在順序的、成塊的、無索引的向檔案塊中寫入資料,并在叢集環境中按塊(block)均勻分布存儲,使用時再根據MapReduce、Spark的并行任務,按塊批次的讀取分析。這樣就把寫入和并行讀取的性能發揮到了極緻,具備了任何建立索引的資料庫都無法比拟的讀寫速度。

傳世的關系模型,巧奪天工的分布式資料庫設計Hadoop生态的分布式資料庫分布式環境下資料庫的一緻性傳世的關系模型

HDFS的資料寫入結構示意圖

上圖是一個寫入HDFS資料的例子,我們需要知道HDFS這些事情:

  • 需要寫入HDFS的檔案會被分成資料塊,一個資料塊通常是64M或者128M。
  • 資料塊在HDFS叢集中預設有三個副本,平均配置設定在不同的DataNode資料節點上。
  • 由于HDFS的分布式架構是中心化管理,是以并沒有資料節點主副的概念,隻有順序的概念,所有資料節點都是存儲資料塊副本的,全部通過namenode節點安排資料節點的寫入順序。
  • 資料節點的寫入過程就像一個資料管道,根據用戶端就近原則,形成資料節點的排隊,當第一個節點寫入資料包後,然後再向資料管道的下一個資料節點複制,以此類推,并得到完成确認。

3. HBase的架構設計

為了更好的了解HBase/Bigtable,一定需要先鋪陳一下它們所依賴的分布式檔案系統基礎環境,然後再看看這些巧奪天工的分布式資料庫設計如何形成的。

由于GFS/HDFS叢集的高性能設計是建立在放棄随機查找的基礎之上。那麼如何既能擁有随機查找的特性,又能充分利用好HDFS/GFS的叢集優勢,而且還能在分布式環境下,具備資料寫入的強一緻性呢?這才湧現出了HBase/Bigtable這類基于分布式檔案系統的分布式資料庫。

但大家要注意了,實際上HBase/Bigtable的随機查找設計目标并不是解決複雜的join關聯查找或二次索引範圍查找,而是實作簡單的一個K-V查詢模型,滿足海量資料的存放條件下,通過主鍵查找結果,能達到毫秒級響應的資料庫。

傳世的關系模型,巧奪天工的分布式資料庫設計Hadoop生态的分布式資料庫分布式環境下資料庫的一緻性傳世的關系模型

HBase的資料寫入結構示意圖

上圖就是HBase的寫入過程以及HDFS作為實體層支撐的架構示意圖。

HBase按照LSM-Tree索引加上SSTable資料結建構立了NoSQL常用的資料存儲模型。寫入過程分成了下面幾個部分:

  • 用戶端向HBase的Region Server寫入資料,會首先進入到WAL(Write-Ahead-Log)預寫日志中,然後再進入到選擇的Region的MemStore中,那這個WAL的目的是什麼呢?保命用的!因為一旦Region Server斷電或異常崩潰,MemStore的資料是在記憶體裡,肯定就丢了,MemStore恢複的時候就靠WAL存的日志資料了。MemStore真正同步資料後,WAL才會從本地寫入HDFS,否則復原。
  • Region的MemStore是一個放在記憶體裡的高速操作區,MVCC事務操作,最近寫入記錄讀取都可以在此處快速完成,當資料在MemStore寫滿後,就會刷入到Store File磁盤存儲區。
  • Store File存儲區就是不斷通過memstore刷盤而形成的HFile,每個HFile預設配置設定128M,大小正好與HDFS的一個資料塊(block)一緻,HFile的實體位置就是存儲在HDFS的每個資料塊中,HFile就是不可更改的了,并通過HDFS的副本機制,形成三副本保證資料的可靠性。

4. HDFS與HBase的協作配合

從上述的HDFS和HBase系統的配合中(GFS與BigTable同理)我們可以看到Hadoop生态體系設計的巧妙結構:

  • HDFS對于大檔案塊的順序寫入,批量分析,HDFS的無索引、順序寫入、管道複制機制充分展現了Google的暴力美學~解決問題的方式務實、簡單、直接、高效。
  • HBase作為列簇設計的K-V資料庫,又實作了細膩入微的設計思想,通過LSM-Tree索引和SSTable資料結建構立起原生資料庫存儲層。
  • HBase機制上WAL、MemStore、StoreFile形成資料操作的多元素協作。
  • HBase架構上HRegion Server、HRegion、HLog、HStore層層嵌套,形成分布式資料庫的叢集化能力。

最關鍵的就是HBase與HDFS的分工思想,HBase解決業務資料記錄寫入,K-V随機查找(毫秒級),由Region Server控制的行級事務等一些列分布式資料庫特征;而HDFS解決小檔案彙聚成大檔案的高性能處理,分布式檔案系統的海量存儲,資料多副本的可靠性,以及成為Mapreduce、Spark、Hive等其他架構與HBase之間協作的基礎平台。

分布式環境下資料庫的一緻性

首先資料庫的一緻性,從傳統的關系型資料庫講,就是指在一個庫中一次業務操作,無論涉及多少張表,多少行集,要麼都失敗,要麼都成功,不能出現結果和預想的不一緻,就是所謂的事務ACID特性中最重要的強一緻性。

事務具有4個特征,分别是原子性、一緻性、隔離性和持久性,簡稱事務的ACID特性;

(一)、原子性(atomicity)

一個事務要麼全部送出成功,要麼全部失敗復原,不能隻執行其中的一部分操作,這就是事務的原子性

(二)、一緻性(consistency)

事務的執行不能破壞資料庫資料的完整性和一緻性,一個事務在執行之前和執行之後,資料庫都必須處于一緻性狀态。

(三)、隔離性(isolation)

事務的隔離性是指在并發環境中,并發的事務互相隔離的,一個事務的執行不能不被其他事務幹擾。

我們重點說說分布式環境下資料庫的一緻性(consistency)特點:

1. MySQL的分布式一緻性

一個特别典型的例子就是MySQL的主從複制架構:異步,半同步,全同步。

  • 異步:盡管主庫保證了資料的強一緻性,但是資料一旦寫給binlog,主庫就無視了從庫的一緻性,繼續忙自己的事情,那麼這個過程就是異步的,從庫從binlog中拿到結果再重放保證與主庫的一緻性,我們把這個過程叫做最終一緻性。
  • 半同步:MySQL 主庫寫入binlog後,至少叢集中任意一個MySQL從庫回報主庫,它同步成功了,那麼主庫就繼續忙自己的事了,我們可以把這個過程稱為弱一緻性。
  • 全同步:自然不用想了,MySQL主庫寫入binlog,叢集其他節點都要重放後,報告同步成功了,主庫才會忙其他事情,這就是分布式環境的強一緻性了!

弱一緻性是在強一緻性和最終一緻性中尋找一個平衡,至少有一個備份點是必須與主保持一緻的,那麼資料的可靠性是不是就提升了,同時性能上也不至于太差了。

2. NoSQL的分布式一緻性

其次糾正一個錯誤的觀點,NoSQL不能都視之為弱一緻性。得具體看是哪個NoSQL架構,例如:MongoDB我們認為是NoSQL,它在副本集模式下,可以靈活地設定一緻性規則,其中majority選項的意思是主庫寫入oplog後,大多數成員需要确認才行。

這個夠撓頭吧,怎麼又來了個大多數,這豈不是在弱一緻性和強一緻性之間又出現了一種一緻性模式,可實際就是這樣。

我們再回來談本文重點提到的一個NoSQL:HBase,它可的确是分布式環境下的強一緻性啦,是不是颠覆了你對NoSQL的認知了!

因為HBase的是基于行級的事務,也就是說當一次寫入記錄的過程,一定是一個Region隻配置設定一個Region Server寫入,而且對于行級資料的操作要不寫入成功,要不失敗。如果一個節點挂了,恢複節點在沒有恢複完資料之前就是不可用了。

HBase在CAP定理中保證了CP,舍棄了A:一緻性C(HBase同一時間寫入不同節點的資料必須一緻),容錯性P(即便有節點出錯,系統還能正常運作),但是這個可靠性A就有問題(必須等待節點恢複完成,對請求就不能立刻有響應了)

傳世的關系模型,巧奪天工的分布式資料庫設計Hadoop生态的分布式資料庫分布式環境下資料庫的一緻性傳世的關系模型

最後再說說有些NoSQL的弱一緻性為什麼就可以被接受? 

回顧一下最開始的MySQL的異步模式複制,它為什麼是MySQL的預設複制模式? 

若滿足最終一緻性,那麼這類分布式系統選擇了CAP定理中的AP,就是說為了保證系統内部無論是否出錯,都會給客戶響應。代價就是分布式各節點的資料副本有可能不一緻,但這個問題不是此類系統業務最在乎的事情,往往系統的高性能,并能為用戶端提供快速響應力才是關鍵目标,MySQL的預設主從複制如此,有些NoSQL亦如此。

傳世的關系模型

首先從資料庫的表達力來講,并不是NoSQL要強于關系模型,事實上SQL的表達力是無出其右的,否則就不會興盛四十年而不衰,就不會有Hive SQL、Spark SQL、Presto、Impala這些以支援SQL互動為起點的NoSQL上層架構存在的必須性。

看吧,還沒到NewSQL這一代的時候,返祖的現象就已經出現了!

1. 我們再溫故知新一下什麼是關系模型:

關系型模型之父Edgar F. Codd,在1970年Communications of ACM 上發表了《大型共享資料庫資料的關系模型》這就是永恒的經典,關系模型的語義設計達到了40年來普世的易于了解,文法的嵌套,閉環,完整。

傳世的關系模型,巧奪天工的分布式資料庫設計Hadoop生态的分布式資料庫分布式環境下資料庫的一緻性傳世的關系模型

關系型模型之父Edgar F. Codd

原始的關系模型:

  • 結構(structure)結構的主要特征就是關系(relation),表格就是實作形式關系定義在類型(type or domain)的基礎上,屬性(attribute)就是類型的實際值,N個屬性就是描述了N元關系每個關系都至少有一個候選鍵(唯一辨別符),它是屬性的組合,通常隻有一個屬性。元組(tuple)就是屬性的集合。
  • 完整性(integrity)實體完整性規則:主鍵屬性不允許null,不能存在任何不比對的外鍵取值。
  • 操作(manipulation)關系的運算符集合(限制、投影、積、交、并、差、連接配接),關系表達式指派關系(例如:關系1 并 關系2指派給關系3),操作的輸入關系和輸出關系,形成了閉包(closure)性質,就可以寫出嵌套表達式。

原始理論具體到實作再翻譯成我們好了解的描述:結構、完整性、操作就構成了現在傳統資料庫的關系模型。

  • 結構:就是我們經常要先對資料庫預先定義的表名和字段(名稱、類型)
  • 完整性:就是表的主鍵不能為空,表與表之間的主外鍵關聯必須保證是完整的,外鍵一定是能找到主鍵的。
  • 操作:那就是SQL表達式啦,SQL的子查詢就是典型的閉包(Closure),可以形成嵌套表達式。

2. 雖然NoSQL很火,但我們這個世界沒法 NO SQL

HBase/Bigtable可以認為是NoSQL的典型代表。

恰恰NoSQL發展至今,出現了Hive SQL,Spark SQL,Presto,Impala,直到基于Google Spanner論文的TIDB,CockroachDB等NewSQL的不斷湧現,才讓我們用實踐證明,無論是NoSQL也好,NewSQL也罷,它們的查詢語言用戶端又回到了SQL。

我們隻是在大資料領域需要替換關系型資料庫的存儲邏輯,使得資料庫更分布式化,更容易實作擴充。這是符合單機性能到了天花闆後,必須橫向擴充的硬需求,但這也并不是說關系模型就過時了!

像HBase/Bigtable這樣的NoSQL,大多數采用了LSM-Tree的索引機制,來替換RDBMS的B-Tree機制,這麼做都是為了能實作記憶體與磁盤,寫入與查找的更平衡利用。

它們又用資料分片的水準切分替換RDBMS的分庫分表的垂直切分,讓節點與叢集的水準伸縮性更為自動化,而不是像分庫分表那樣進行人工複雜的介入。

TiDB這些NewSQL的出現恰恰是在縫合關系模型和分布式存儲之間的裂縫,面向用戶端依然是關系模型,強化分布式業務更新的強一緻性(分布式事務,這是最難的最複雜的地方),面向存儲則堅定的選擇K-V模型。

例如TIDB的TIKV叢集采用的就是rocksdb,rocksdb的底層索引機制又和HBase/Bigtable采用相同設計機制的又一個nosql成員。

是以并不是Google的Spanner論文以及F1,TiDB這些實作技術開了曆史的倒車,恰恰是對狂熱的nosql運動的一種反思,對成為經典的SQL關系模型理論的一種認真思考和融合。

任何新技術都是站在前輩的基礎上開啟的,我們總要回頭望望,反思新技術的運用到底我們得到了什麼,又失去了什麼!

作者:西安守護石資訊科技CTO