传世的关系模型,巧夺天工的分布式数据库设计
Hadoop生態(tài)的分布式數(shù)據(jù)庫(kù)
1、什么是分布式數(shù)據(jù)庫(kù)?
從狹義的理解就是分布式關(guān)系型數(shù)據(jù)庫(kù),主要特指目前熱門(mén)的NewSQL。
從廣義的理解,分庫(kù)分表的傳統(tǒng)關(guān)系型數(shù)據(jù)庫(kù),傳統(tǒng)關(guān)系型數(shù)據(jù)庫(kù)集群,關(guān)系型數(shù)據(jù)庫(kù)的主從架構(gòu),分布式KV數(shù)據(jù)庫(kù)(例如:HBase),分布式文檔數(shù)據(jù)庫(kù)(例如:MongoDB),分布式關(guān)系數(shù)據(jù)庫(kù)(例如:TiDB)等,統(tǒng)稱(chēng)為分布式數(shù)據(jù)庫(kù)。
本文主要講Google一脈相承的Hadoop生態(tài)下的分布式數(shù)據(jù)庫(kù)架構(gòu)設(shè)計(jì),以及傳統(tǒng)RDBMS與NoSQL的分布式環(huán)境下的一致性對(duì)比。
2、Hadoop HDFS的數(shù)據(jù)存儲(chǔ)模型
最早Google發(fā)明了GFS分布式文件系統(tǒng),之后對(duì)應(yīng)的開(kāi)源項(xiàng)目就是鼎鼎大名的Hadoop HDFS。
GFS/HDFS的特點(diǎn)表現(xiàn)在順序的、成塊的、無(wú)索引的向文件塊中寫(xiě)入數(shù)據(jù),并在集群環(huán)境中按塊(block)均勻分布存儲(chǔ),使用時(shí)再根據(jù)MapReduce、Spark的并行任務(wù),按塊批次的讀取分析。這樣就把寫(xiě)入和并行讀取的性能發(fā)揮到了極致,具備了任何建立索引的數(shù)據(jù)庫(kù)都無(wú)法比擬的讀寫(xiě)速度。
HDFS的數(shù)據(jù)寫(xiě)入結(jié)構(gòu)示意圖
上圖是一個(gè)寫(xiě)入HDFS數(shù)據(jù)的例子,我們需要知道HDFS這些事情:
需要寫(xiě)入HDFS的文件會(huì)被分成數(shù)據(jù)塊,一個(gè)數(shù)據(jù)塊通常是64M或者128M。
數(shù)據(jù)塊在HDFS集群中默認(rèn)有三個(gè)副本,平均分配在不同的DataNode數(shù)據(jù)節(jié)點(diǎn)上。
由于HDFS的分布式架構(gòu)是中心化管理,因此并沒(méi)有數(shù)據(jù)節(jié)點(diǎn)主副的概念,只有順序的概念,所有數(shù)據(jù)節(jié)點(diǎn)都是存儲(chǔ)數(shù)據(jù)塊副本的,全部通過(guò)namenode節(jié)點(diǎn)安排數(shù)據(jù)節(jié)點(diǎn)的寫(xiě)入順序。
數(shù)據(jù)節(jié)點(diǎn)的寫(xiě)入過(guò)程就像一個(gè)數(shù)據(jù)管道,根據(jù)客戶端就近原則,形成數(shù)據(jù)節(jié)點(diǎn)的排隊(duì),當(dāng)?shù)谝粋€(gè)節(jié)點(diǎn)寫(xiě)入數(shù)據(jù)包后,然后再向數(shù)據(jù)管道的下一個(gè)數(shù)據(jù)節(jié)點(diǎn)復(fù)制,以此類(lèi)推,并得到完成確認(rèn)。
3、HBase的架構(gòu)設(shè)計(jì)
為了更好的理解HBase/Bigtable,一定需要先鋪陳一下它們所依賴的分布式文件系統(tǒng)基礎(chǔ)環(huán)境,然后再看看這些巧奪天工的分布式數(shù)據(jù)庫(kù)設(shè)計(jì)如何形成的。
由于GFS/HDFS集群的高性能設(shè)計(jì)是建立在放棄隨機(jī)查找的基礎(chǔ)之上。那么如何既能擁有隨機(jī)查找的特性,又能充分利用好HDFS/GFS的集群優(yōu)勢(shì),而且還能在分布式環(huán)境下,具備數(shù)據(jù)寫(xiě)入的強(qiáng)一致性呢?這才涌現(xiàn)出了HBase/Bigtable這類(lèi)基于分布式文件系統(tǒng)的分布式數(shù)據(jù)庫(kù)。
但大家要注意了,實(shí)際上HBase/Bigtable的隨機(jī)查找設(shè)計(jì)目標(biāo)并不是解決復(fù)雜的join關(guān)聯(lián)查找或二次索引范圍查找,而是實(shí)現(xiàn)簡(jiǎn)單的一個(gè)K-V查詢模型,滿足海量數(shù)據(jù)的存放條件下,通過(guò)主鍵查找結(jié)果,能達(dá)到毫秒級(jí)響應(yīng)的數(shù)據(jù)庫(kù)。
HBase的數(shù)據(jù)寫(xiě)入結(jié)構(gòu)示意圖
上圖就是HBase的寫(xiě)入過(guò)程以及HDFS作為物理層支撐的架構(gòu)示意圖。
HBase按照LSM-Tree索引加上SSTable數(shù)據(jù)結(jié)構(gòu)建立了NoSQL常用的數(shù)據(jù)存儲(chǔ)模型。寫(xiě)入過(guò)程分成了下面幾個(gè)部分:
客戶端向HBase的Region Server寫(xiě)入數(shù)據(jù),會(huì)首先進(jìn)入到WAL(Write-Ahead-Log)預(yù)寫(xiě)日志中,然后再進(jìn)入到選擇的Region的MemStore中,那這個(gè)WAL的目的是什么呢?保命用的!因?yàn)橐坏㏑egion Server斷電或異常崩潰,MemStore的數(shù)據(jù)是在內(nèi)存里,肯定就丟了,MemStore恢復(fù)的時(shí)候就靠WAL存的日志數(shù)據(jù)了。MemStore真正同步數(shù)據(jù)后,WAL才會(huì)從本地寫(xiě)入HDFS,否則回滾。
Region的MemStore是一個(gè)放在內(nèi)存里的高速操作區(qū),MVCC事務(wù)操作,最近寫(xiě)入記錄讀取都可以在此處快速完成,當(dāng)數(shù)據(jù)在MemStore寫(xiě)滿后,就會(huì)刷入到Store File磁盤(pán)存儲(chǔ)區(qū)。
Store File存儲(chǔ)區(qū)就是不斷通過(guò)memstore刷盤(pán)而形成的HFile,每個(gè)HFile默認(rèn)分配128M,大小正好與HDFS的一個(gè)數(shù)據(jù)塊(block)一致,HFile的物理位置就是存儲(chǔ)在HDFS的每個(gè)數(shù)據(jù)塊中,HFile就是不可更改的了,并通過(guò)HDFS的副本機(jī)制,形成三副本保證數(shù)據(jù)的可靠性。
3、HDFS與HBase的協(xié)作配合
從上述的HDFS和HBase系統(tǒng)的配合中(GFS與BigTable同理)我們可以看到Hadoop生態(tài)體系設(shè)計(jì)的巧妙結(jié)構(gòu):
HDFS對(duì)于大文件塊的順序?qū)懭?#xff0c;批量分析,HDFS的無(wú)索引、順序?qū)懭搿⒐艿缽?fù)制機(jī)制充分體現(xiàn)了Google的暴力美學(xué)~解決問(wèn)題的方式務(wù)實(shí)、簡(jiǎn)單、直接、高效。
HBase作為列簇設(shè)計(jì)的K-V數(shù)據(jù)庫(kù),又實(shí)現(xiàn)了細(xì)膩入微的設(shè)計(jì)思想,通過(guò)LSM-Tree索引和SSTable數(shù)據(jù)結(jié)構(gòu)建立起原生數(shù)據(jù)庫(kù)存儲(chǔ)層。
HBase機(jī)制上WAL、MemStore、StoreFile形成數(shù)據(jù)操作的多元素協(xié)作。
HBase架構(gòu)上HRegion Server、HRegion、HLog、HStore層層嵌套,形成分布式數(shù)據(jù)庫(kù)的集群化能力。
最關(guān)鍵的就是HBase與HDFS的分工思想,HBase解決業(yè)務(wù)數(shù)據(jù)記錄寫(xiě)入,K-V隨機(jī)查找(毫秒級(jí)),由Region Server控制的行級(jí)事務(wù)等一些列分布式數(shù)據(jù)庫(kù)特征;而HDFS解決小文件匯聚成大文件的高性能處理,分布式文件系統(tǒng)的海量存儲(chǔ),數(shù)據(jù)多副本的可靠性,以及成為Mapreduce、Spark、Hive等其他框架與HBase之間協(xié)作的基礎(chǔ)平臺(tái)。
?
分布式環(huán)境下數(shù)據(jù)庫(kù)的一致性
首先數(shù)據(jù)庫(kù)的一致性,從傳統(tǒng)的關(guān)系型數(shù)據(jù)庫(kù)講,就是指在一個(gè)庫(kù)中一次業(yè)務(wù)操作,無(wú)論涉及多少?gòu)埍?#xff0c;多少行集,要么都失敗,要么都成功,不能出現(xiàn)結(jié)果和預(yù)想的不一致,就是所謂的事務(wù)ACID特性中最重要的強(qiáng)一致性。
事務(wù)具有4個(gè)特征,分別是原子性、一致性、隔離性和持久性,簡(jiǎn)稱(chēng)事務(wù)的ACID特性;
(一)、原子性(atomicity)
一個(gè)事務(wù)要么全部提交成功,要么全部失敗回滾,不能只執(zhí)行其中的一部分操作,這就是事務(wù)的原子性
(二)、一致性(consistency)
事務(wù)的執(zhí)行不能破壞數(shù)據(jù)庫(kù)數(shù)據(jù)的完整性和一致性,一個(gè)事務(wù)在執(zhí)行之前和執(zhí)行之后,數(shù)據(jù)庫(kù)都必須處于一致性狀態(tài)。
(三)、隔離性(isolation)
事務(wù)的隔離性是指在并發(fā)環(huán)境中,并發(fā)的事務(wù)相互隔離的,一個(gè)事務(wù)的執(zhí)行不能不被其他事務(wù)干擾。
我們重點(diǎn)說(shuō)說(shuō)分布式環(huán)境下數(shù)據(jù)庫(kù)的一致性(consistency)特點(diǎn):
1、MySQL的分布式一致性
一個(gè)特別典型的例子就是MySQL的主從復(fù)制架構(gòu):異步,半同步,全同步。
異步:盡管主庫(kù)保證了數(shù)據(jù)的強(qiáng)一致性,但是數(shù)據(jù)一旦寫(xiě)給binlog,主庫(kù)就無(wú)視了從庫(kù)的一致性,繼續(xù)忙自己的事情,那么這個(gè)過(guò)程就是異步的,從庫(kù)從binlog中拿到結(jié)果再重放保證與主庫(kù)的一致性,我們把這個(gè)過(guò)程叫做最終一致性。
半同步:MySQL 主庫(kù)寫(xiě)入binlog后,至少集群中任意一個(gè)MySQL從庫(kù)反饋主庫(kù),它同步成功了,那么主庫(kù)就繼續(xù)忙自己的事了,我們可以把這個(gè)過(guò)程稱(chēng)為弱一致性。
全同步:自然不用想了,MySQL主庫(kù)寫(xiě)入binlog,集群其他節(jié)點(diǎn)都要重放后,報(bào)告同步成功了,主庫(kù)才會(huì)忙其他事情,這就是分布式環(huán)境的強(qiáng)一致性了!
弱一致性是在強(qiáng)一致性和最終一致性中尋找一個(gè)平衡,至少有一個(gè)備份點(diǎn)是必須與主保持一致的,那么數(shù)據(jù)的可靠性是不是就提升了,同時(shí)性能上也不至于太差了。
2、NoSQL的分布式一致性
其次糾正一個(gè)錯(cuò)誤的觀點(diǎn),NoSQL不能都視之為弱一致性。得具體看是哪個(gè)NoSQL框架,例如:MongoDB我們認(rèn)為是NoSQL,它在副本集模式下,可以靈活地設(shè)置一致性規(guī)則,其中majority選項(xiàng)的意思是主庫(kù)寫(xiě)入oplog后,大多數(shù)成員需要確認(rèn)才行。
這個(gè)夠撓頭吧,怎么又來(lái)了個(gè)大多數(shù),這豈不是在弱一致性和強(qiáng)一致性之間又出現(xiàn)了一種一致性模式,可實(shí)際就是這樣。
我們?cè)倩貋?lái)談本文重點(diǎn)提到的一個(gè)NoSQL:HBase,它可的確是分布式環(huán)境下的強(qiáng)一致性啦,是不是顛覆了你對(duì)NoSQL的認(rèn)知了!
因?yàn)镠Base的是基于行級(jí)的事務(wù),也就是說(shuō)當(dāng)一次寫(xiě)入記錄的過(guò)程,一定是一個(gè)Region只分配一個(gè)Region Server寫(xiě)入,而且對(duì)于行級(jí)數(shù)據(jù)的操作要不寫(xiě)入成功,要不失敗。如果一個(gè)節(jié)點(diǎn)掛了,恢復(fù)節(jié)點(diǎn)在沒(méi)有恢復(fù)完數(shù)據(jù)之前就是不可用了。
HBase在CAP定理中保證了CP,舍棄了A:一致性C(HBase同一時(shí)間寫(xiě)入不同節(jié)點(diǎn)的數(shù)據(jù)必須一致),容錯(cuò)性P(即便有節(jié)點(diǎn)出錯(cuò),系統(tǒng)還能正常運(yùn)行),但是這個(gè)可靠性A就有問(wèn)題(必須等待節(jié)點(diǎn)恢復(fù)完成,對(duì)請(qǐng)求就不能立刻有響應(yīng)了)
最后再說(shuō)說(shuō)有些NoSQL的弱一致性為什么就可以被接受??
回顧一下最開(kāi)始的MySQL的異步模式復(fù)制,它為什么是MySQL的默認(rèn)復(fù)制模式??
若滿足最終一致性,那么這類(lèi)分布式系統(tǒng)選擇了CAP定理中的AP,就是說(shuō)為了保證系統(tǒng)內(nèi)部無(wú)論是否出錯(cuò),都會(huì)給客戶響應(yīng)。代價(jià)就是分布式各節(jié)點(diǎn)的數(shù)據(jù)副本有可能不一致,但這個(gè)問(wèn)題不是此類(lèi)系統(tǒng)業(yè)務(wù)最在乎的事情,往往系統(tǒng)的高性能,并能為客戶端提供快速響應(yīng)力才是關(guān)鍵目標(biāo),MySQL的默認(rèn)主從復(fù)制如此,有些NoSQL亦如此。
?
傳世的關(guān)系模型
首先從數(shù)據(jù)庫(kù)的表達(dá)力來(lái)講,并不是NoSQL要強(qiáng)于關(guān)系模型,事實(shí)上SQL的表達(dá)力是無(wú)出其右的,否則就不會(huì)興盛四十年而不衰,就不會(huì)有Hive SQL、Spark SQL、Presto、Impala這些以支持SQL交互為起點(diǎn)的NoSQL上層框架存在的必須性。
看吧,還沒(méi)到NewSQL這一代的時(shí)候,返祖的現(xiàn)象就已經(jīng)出現(xiàn)了!
1、我們?cè)贉毓手乱幌率裁词顷P(guān)系模型:
關(guān)系型模型之父Edgar F. Codd,在1970年Communications of ACM 上發(fā)表了《大型共享數(shù)據(jù)庫(kù)數(shù)據(jù)的關(guān)系模型》這就是永恒的經(jīng)典,關(guān)系模型的語(yǔ)義設(shè)計(jì)達(dá)到了40年來(lái)普世的易于理解,語(yǔ)法的嵌套,閉環(huán),完整。
關(guān)系型模型之父Edgar F. Codd
原始的關(guān)系模型:
結(jié)構(gòu)(structure)結(jié)構(gòu)的主要特征就是關(guān)系(relation),表格就是實(shí)現(xiàn)形式關(guān)系定義在類(lèi)型(type or domain)的基礎(chǔ)上,屬性(attribute)就是類(lèi)型的實(shí)際值,N個(gè)屬性就是描述了N元關(guān)系每個(gè)關(guān)系都至少有一個(gè)候選鍵(唯一標(biāo)識(shí)符),它是屬性的組合,通常只有一個(gè)屬性。元組(tuple)就是屬性的集合
完整性(integrity)實(shí)體完整性規(guī)則:主鍵屬性不允許null,不能存在任何不匹配的外鍵取值。
操作(manipulation)關(guān)系的運(yùn)算符集合(限制、投影、積、交、并、差、連接),關(guān)系表達(dá)式賦值關(guān)系(例如:關(guān)系1 并 關(guān)系2賦值給關(guān)系3),操作的輸入關(guān)系和輸出關(guān)系,形成了閉包(closure)性質(zhì),就可以寫(xiě)出嵌套表達(dá)式
原始理論具體到實(shí)現(xiàn)再翻譯成我們好理解的描述:結(jié)構(gòu)、完整性、操作就構(gòu)成了現(xiàn)在傳統(tǒng)數(shù)據(jù)庫(kù)的關(guān)系模型。
結(jié)構(gòu):就是我們經(jīng)常要先對(duì)數(shù)據(jù)庫(kù)預(yù)先定義的表名和字段(名稱(chēng)、類(lèi)型)
完整性:就是表的主鍵不能為空,表與表之間的主外鍵關(guān)聯(lián)必須保證是完整的,外鍵一定是能找到主鍵的。
操作:那就是SQL表達(dá)式啦,SQL的子查詢就是典型的閉包(Closure),可以形成嵌套表達(dá)式。
2、雖然NoSQL很火,但我們這個(gè)世界沒(méi)法 NO SQL
HBase/Bigtable可以認(rèn)為是NoSQL的典型代表
恰恰NoSQL發(fā)展至今,出現(xiàn)了Hive SQL,Spark SQL,Presto,Impala,直到基于Google Spanner論文的TIDB,CockroachDB等NewSQL的不斷涌現(xiàn),才讓我們用實(shí)踐證明,無(wú)論是NoSQL也好,NewSQL也罷,它們的查詢語(yǔ)言客戶端又回到了SQL。
我們只是在大數(shù)據(jù)領(lǐng)域需要替換關(guān)系型數(shù)據(jù)庫(kù)的存儲(chǔ)邏輯,使得數(shù)據(jù)庫(kù)更分布式化,更容易實(shí)現(xiàn)擴(kuò)展。這是符合單機(jī)性能到了天花板后,必須橫向擴(kuò)展的硬需求,但這也并不是說(shuō)關(guān)系模型就過(guò)時(shí)了!
像HBase/Bigtable這樣的NoSQL,大多數(shù)采用了LSM-Tree的索引機(jī)制,來(lái)替換RDBMS的B-Tree機(jī)制,這么做都是為了能實(shí)現(xiàn)內(nèi)存與磁盤(pán),寫(xiě)入與查找的更平衡利用。
它們又用數(shù)據(jù)分片的水平切分替換RDBMS的分庫(kù)分表的垂直切分,讓節(jié)點(diǎn)與集群的水平伸縮性更為自動(dòng)化,而不是像分庫(kù)分表那樣進(jìn)行人工復(fù)雜的介入。
TiDB這些NewSQL的出現(xiàn)恰恰是在縫合關(guān)系模型和分布式存儲(chǔ)之間的裂縫,面向客戶端依然是關(guān)系模型,強(qiáng)化分布式業(yè)務(wù)更新的強(qiáng)一致性(分布式事務(wù),這是最難的最復(fù)雜的地方),面向存儲(chǔ)則堅(jiān)定的選擇K-V模型。
例如TIDB的TIKV集群采用的就是rocksdb,rocksdb的底層索引機(jī)制又和HBase/Bigtable采用相同設(shè)計(jì)機(jī)制的又一個(gè)nosql成員。
因此并不是Google的Spanner論文以及F1,TiDB這些實(shí)現(xiàn)技術(shù)開(kāi)了歷史的倒車(chē),恰恰是對(duì)狂熱的nosql運(yùn)動(dòng)的一種反思,對(duì)成為經(jīng)典的SQL關(guān)系模型理論的一種認(rèn)真思考和融合。
任何新技術(shù)都是站在前輩的基礎(chǔ)上開(kāi)啟的,我們總要回頭望望,反思新技術(shù)的運(yùn)用到底我們得到了什么,又失去了什么!
有道無(wú)術(shù),術(shù)可成;有術(shù)無(wú)道,止于術(shù)
歡迎大家關(guān)注Java之道公眾號(hào)
好文章,我在看??
?
?
?
?
總結(jié)
以上是生活随笔為你收集整理的传世的关系模型,巧夺天工的分布式数据库设计的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: list dict 性能测试
- 下一篇: 面试时说Redis是单线程的,被喷惨了!