用关系型NoSQL回到未来
隨著為分布式世界重建遺留RDBMS (ACID事務(wù)、關(guān)系、約束、規(guī)范化建模)的原語(yǔ),數(shù)據(jù)庫(kù)世界正在經(jīng)歷復(fù)興。
這些新的系統(tǒng)從技術(shù)上來(lái)說(shuō)是CP而不是AP,但是有很高的容錯(cuò)性。
這些系統(tǒng)大多數(shù)依賴于Google的Spanner或Percolator協(xié)議,使用兩階段鎖,需要物理的同步時(shí)鐘來(lái)保證一致性。
一些系統(tǒng)采用基于Calvin協(xié)議的預(yù)提交方法,比如FaunaDB,不需要特別的硬件就能提供更強(qiáng)的保障。
在這兩種情況下,系統(tǒng)開(kāi)發(fā)人員不再需要放棄事務(wù)來(lái)獲得現(xiàn)實(shí)世界中的可伸縮性和可用性。
數(shù)據(jù)庫(kù)復(fù)興運(yùn)動(dòng)起源于NoSQL,大約是因?yàn)?008年新的一大波互聯(lián)網(wǎng)公司(Twitter、Facebook、Google、Amazon)的技術(shù)需求遠(yuǎn)超傳統(tǒng)的RDBMS能力。另外,像Oracle這樣的RDBMS供應(yīng)商的價(jià)格體系不能夠支持這些新興公司的較小單位經(jīng)濟(jì)效益,尤其是廣告支持的公司。在這種情況下要怎么做呢?
一開(kāi)始,公司會(huì)使用遺留數(shù)據(jù)庫(kù)作為存儲(chǔ)引擎的自定義、分布式數(shù)據(jù)分片服務(wù),尤其是MySQL和InnoDB。像Memcache和之后的Redis這樣的分布式緩存無(wú)處不在。然而,這些系統(tǒng)不是自運(yùn)維的,它們?nèi)匀恍枰狣BA的干預(yù)才能從失敗中恢復(fù)。它們不是自動(dòng)分片的,也不是自修復(fù)的。
當(dāng)時(shí),我在Twitter管理軟件基礎(chǔ)設(shè)施團(tuán)隊(duì),對(duì)我們而言,完全有可能構(gòu)建一個(gè)可以透明地大規(guī)模和靈活交付的系統(tǒng),因此,連同業(yè)內(nèi)的其他人,我們開(kāi)始將其作為開(kāi)源項(xiàng)目著手來(lái)做,一開(kāi)始主要是寄希望于Apache Cassandra、Hadoop和其他存儲(chǔ)平臺(tái)。當(dāng)你的業(yè)務(wù)規(guī)模變大的時(shí)候,任何會(huì)阻礙它前進(jìn)的東西都需要放棄。
這些數(shù)據(jù)庫(kù)系統(tǒng)的商業(yè)供應(yīng)商號(hào)稱他們的系統(tǒng)不能提供某些RDBMS傳統(tǒng)功能,因?yàn)闆](méi)人需要這些功能,但這顯然是錯(cuò)誤的。現(xiàn)在每個(gè)企業(yè)都需要擴(kuò)大規(guī)模,然而我們?yōu)榱耸褂肗oSQL放棄了什么呢?我們能把放棄的東西拿回來(lái)嗎?
最終一致性的實(shí)踐效果
CAP理論可以有效地概括為:當(dāng)網(wǎng)絡(luò)分片時(shí)會(huì)發(fā)生什么?系統(tǒng)會(huì)保證一致性(正確性)而暫時(shí)停一下,還是為了保證可用性,而盡最大努力保證它的運(yùn)行?其實(shí)在實(shí)踐中,一致性和可用性的選擇是模棱兩可的,真實(shí)世界的情況更加微妙。
第一代NoSQL系統(tǒng)是最終一致的,在分區(qū)事件發(fā)生之后,它們會(huì)在可變但有限的一段時(shí)間之內(nèi)協(xié)調(diào)沖突,對(duì)數(shù)據(jù)進(jìn)行概率投票。在現(xiàn)實(shí)世界中,很少有這么復(fù)雜的最終一致性系統(tǒng),相反,它們使用基于本地系統(tǒng)時(shí)間的簡(jiǎn)單“最后一次寫入獲勝”機(jī)制。即使它再智能,對(duì)搭建應(yīng)用程序也沒(méi)有實(shí)質(zhì)上的幫助。它需要系統(tǒng)設(shè)計(jì)人員將整個(gè)主機(jī)的沖突解決功能引入到應(yīng)用程序?qū)印?/p>
舉個(gè)例子
明顯的交易失敗模式如下所示:
Bob在ATM存了200美元。
數(shù)據(jù)庫(kù)分片接受Bob的“最終一致”存款。他的賬戶余額200美金更新需要排隊(duì)等待。
Bob又通過(guò)移動(dòng)應(yīng)用程序存了100美元。這次交易更新使用了另一個(gè)分片,并復(fù)制給其他的集群,但沒(méi)有到原來(lái)的分片。
網(wǎng)絡(luò)恢復(fù),復(fù)制發(fā)生。
由于第二個(gè)交易發(fā)生的時(shí)間比較晚,所以Bob的余額根據(jù)第3步的分片被更新為100美元。
Bob現(xiàn)在損失了200美元現(xiàn)金。最終一致性能保證可用性。在這種情況下,我們存錢的數(shù)目多少并不能保證正確。
CRDT和區(qū)塊鏈
為了解決這個(gè)問(wèn)題,人們想出了各種方案,特別是CRDT(conflict-free replicated data types),它能幫助有效地關(guān)閉所有的中間狀態(tài),保證最終值正確重建。在這種情況下,Bob的交易會(huì)被記錄為借方和貸方,而不只是最終余額。最終余額的獲得可以在數(shù)據(jù)庫(kù)或應(yīng)用程序?qū)又型瓿伞R环N例子是區(qū)塊鏈,它會(huì)記錄集群上所有節(jié)點(diǎn)每時(shí)每刻的交易。
然而,在實(shí)際操作中,這不能解決所有的問(wèn)題,因?yàn)閿?shù)據(jù)庫(kù)不是封閉的系統(tǒng)。任何數(shù)據(jù)讀寫的重點(diǎn)在于協(xié)調(diào)外部影響。如果Bob從ATM取出現(xiàn)金,即使之后CRDT顯示當(dāng)時(shí)他的余額不足,但是錢也被拿走了。
這并不是一個(gè)完全的理論問(wèn)題。惡意使用ATM的漏洞是一種欺詐行為。因此,數(shù)據(jù)庫(kù)需要“外部一致性”,就是俗稱的ACID屬性。
遺留解決方案
遺留數(shù)據(jù)庫(kù)(通常是集中的RDBMS)通過(guò)非分布式來(lái)解決這個(gè)問(wèn)題。其實(shí)說(shuō)到底,就是一個(gè)有單個(gè)磁盤的單機(jī),并且出于實(shí)際目的,該磁盤基于一個(gè)互斥鎖進(jìn)行更新,事實(shí)就是這么回事。對(duì)狀態(tài)的更新是序列化的,這代表它們是根據(jù)單一、確定的順序發(fā)生的,并且是外部一致的,對(duì)應(yīng)著實(shí)際發(fā)生順序。任何規(guī)模化都是出于單機(jī)的垂直擴(kuò)展。
該模型很方便實(shí)現(xiàn),但不能滿足很多關(guān)鍵需求,特別是和可用性相關(guān)的問(wèn)題。
因此我們迎來(lái)了主從復(fù)制系統(tǒng),主節(jié)點(diǎn)可以被DBA手動(dòng)替換為從節(jié)點(diǎn),該從節(jié)點(diǎn)異步地復(fù)制了主節(jié)點(diǎn)的狀態(tài)。這雖然不是很好,但是不像最終一致性分布式系統(tǒng),不一致的范圍是已知的:恰恰是最后一次事務(wù)復(fù)制到從節(jié)點(diǎn),而主節(jié)點(diǎn)發(fā)生了外部可見(jiàn)的故障,這之間就出現(xiàn)了不一致情況。
這是互聯(lián)網(wǎng)分片系統(tǒng)真實(shí)運(yùn)行的情況:
- 它們可以在分片(單機(jī))中執(zhí)行交易。
- 它們可以手動(dòng)或半手動(dòng)地將故障備份到備份分片上。
- 它們不能同時(shí)在多分片進(jìn)行事務(wù)處理。
對(duì)于Twitter和Facebook來(lái)說(shuō)這勉強(qiáng)可行,但并不可取。比如說(shuō),如果在手機(jī)上得到的消息通知在網(wǎng)站上不能讀,這是很奇怪的,但這并不是災(zāi)難性的。需要事務(wù)處理的產(chǎn)品特性(例如,用戶名分配)在遺留的RDBMS中沒(méi)有那么大的伸縮性。
但是隨著產(chǎn)品變得越來(lái)越復(fù)雜,缺乏外部一致性的劣勢(shì)也變得更加嚴(yán)重。
Google Spanner
Spanner是Google對(duì)于這兩個(gè)問(wèn)題的解決方法。最初它只在Google內(nèi)部的基礎(chǔ)設(shè)施上使用,現(xiàn)在作為托管產(chǎn)品在Google Cloud上可以獲得。
它完成了兩件事:
- 多分片事務(wù)通過(guò)兩階段準(zhǔn)備/提交算法實(shí)現(xiàn),基本上類似于20世紀(jì)80年代的事務(wù)監(jiān)控協(xié)議Tuxedo。
- 不再依賴HA或是主機(jī)級(jí)別的硬件來(lái)保證可用性,通過(guò)Paxos自動(dòng)實(shí)現(xiàn)商品硬件的分片故障轉(zhuǎn)移。
這個(gè)方法在某種程度上很有效果。它保證了可串行化,能根據(jù)實(shí)時(shí)順序?qū)γ總€(gè)單獨(dú)的分片進(jìn)行更新。但它不能保證外部一致性,也不能保證分片之間的實(shí)時(shí)協(xié)調(diào)。為了解決這個(gè)問(wèn)題,Spanner需要做這件事:
- 物理原子鐘硬件在很小的誤差范圍之內(nèi)同步所有分片上的系統(tǒng)時(shí)間。
現(xiàn)在事務(wù)協(xié)調(diào)器就能放心地說(shuō):“分片們,我在T時(shí)間做了一個(gè)事務(wù),如果你沒(méi)有看到在我們共享時(shí)間誤差范圍內(nèi)的其他任何更新,那就是不沖突的”。這引發(fā)了每次最終一致讀寫間的小延遲,因?yàn)槊總€(gè)分片都需要等待時(shí)鐘模糊窗口。
除去延遲的影響,這對(duì)Google來(lái)說(shuō)很可行。它們有資源來(lái)構(gòu)建并管理自定義的原子時(shí)鐘硬件和有限延遲的網(wǎng)絡(luò)。然而,有許多新的數(shù)據(jù)庫(kù)系統(tǒng)在沒(méi)有原子鐘的情況下實(shí)現(xiàn)類似的協(xié)議,但總是要付出代價(jià)的。
基于NTP的Spanner
基于NTP時(shí)鐘同步的數(shù)據(jù)庫(kù)有更長(zhǎng)的模糊窗口,通常需要幾百毫秒。實(shí)踐中,這些系統(tǒng)完全放棄等待,轉(zhuǎn)而保證沒(méi)有外部一致性的單記錄可串行化。這可能會(huì)導(dǎo)致類似的交叉線模列和雙借方效果。
它們還不提供快速地外部可串行化讀取,通常從最后一個(gè)已知的Paxos leader這里讀取。這可能違背了可串行化,因?yàn)閘eader可能不知道它已經(jīng)被廢棄,于是在選舉窗口(通常是幾秒鐘)愉快地提供了已經(jīng)廢棄的值。要預(yù)防這個(gè)窗口的發(fā)生需要暫停。
最后,時(shí)鐘是否會(huì)碰巧不同步,這也是Google花費(fèi)心思需要預(yù)防的,因?yàn)樵谠浦腥魏闻c時(shí)鐘無(wú)關(guān)的事件,比如VM停頓,都會(huì)造成這個(gè)情況的發(fā)生,甚至寫端的可串行化保證都會(huì)丟失。
Google Percolator
另一類數(shù)據(jù)庫(kù)查詢單個(gè)物理時(shí)鐘(Google Percolator的論文中稱其為”clock oracle”)擁有類似共享時(shí)鐘的往返互聯(lián)網(wǎng)延遲的模糊窗口,更糟糕的是,還會(huì)遇到明顯的單點(diǎn)故障。
這個(gè)模型類似于多處理器RDBMS,它也用了單個(gè)物理時(shí)鐘,因?yàn)樗菃螜C(jī),但是系統(tǒng)總線被網(wǎng)絡(luò)所取代。在實(shí)踐中,這些系統(tǒng)放棄了多區(qū)域擴(kuò)展,受限于單個(gè)數(shù)據(jù)中心。
很明顯沒(méi)有物理時(shí)鐘同步,分布式外部一致性是不可能的,還是有其他方法?
使用Calvin規(guī)避物理時(shí)鐘
如果你可以創(chuàng)造給所有的事務(wù)服務(wù)的邏輯clock oracle,不依賴于任何單個(gè)物理機(jī)器,還可以廣泛分布,那怎么樣?這就是Calvin完成的工作。Calvin是耶魯大學(xué)Daniel Abadi實(shí)驗(yàn)室開(kāi)發(fā)的。
John Calvin是法國(guó)新教改革者,他相信每個(gè)人都有最終的宿命,無(wú)論是上天堂還是下地獄,都是上帝在創(chuàng)造世界之前決定的。
這也是Calvin的機(jī)制。事務(wù)的順序是預(yù)處理決定的,節(jié)點(diǎn)的子集作為分區(qū)的Oracle,給一系列流水線批處理中傳入的事務(wù)分配外部一致的順序。之后,批處理用10毫秒的時(shí)間提交到分布式提前寫日志,可以用Paxos或Raft實(shí)現(xiàn)。
這種預(yù)處理有很多好處:
- 它可以在單個(gè)網(wǎng)絡(luò)往返中完成提交到分布式日志,不需要副本上的兩階段鎖。
- 它的操作拓?fù)浜透北就負(fù)洳煌?#xff0c;減少了長(zhǎng)尾延遲。
- 可串行化讀不需要協(xié)調(diào),也不需要等待模糊窗口。相反,它們像最終一致性系統(tǒng)那樣在全局內(nèi)擴(kuò)展。
然而,它肯定會(huì)做出一些讓步:
- 由于事務(wù)是分批提交的,寫延遲不能低于等待下次提交的時(shí)間,平均約為5毫秒,最多可到10毫秒。
FaunaDB進(jìn)行了一系列性能改進(jìn),實(shí)現(xiàn)了這個(gè)模型,是個(gè)關(guān)系型NoSQL系統(tǒng),而不是NewSQL系統(tǒng),但是沒(méi)有什么特別阻礙FaunaDB最終實(shí)現(xiàn)SQL接口的東西。
CAP
盡管沒(méi)有CP系統(tǒng)可以在完全任意分區(qū)事件中保持活動(dòng)性,但是在實(shí)踐中,我們能發(fā)現(xiàn)Spanner和FaunaDB云系統(tǒng)和AP系統(tǒng)的可用性類似。超過(guò)99.9%的可用性故障可能都來(lái)自于實(shí)現(xiàn)的問(wèn)題,也可能來(lái)自于硬件和網(wǎng)絡(luò)的故障,CP系統(tǒng)的一致性模型可以讓它們比AP系統(tǒng)更容易地在故障下驗(yàn)證。
比如說(shuō),五個(gè)數(shù)據(jù)中心的FaunaDB集群可以承受丟失兩個(gè)完整的數(shù)據(jù)中心,而不影響活動(dòng)性。同時(shí),類似FaunaDB的CP系統(tǒng)通常可以在較低的一致性級(jí)別下維持讀的可用性(比如快照隔離的情況),甚至在分區(qū)事件的時(shí)候也能實(shí)現(xiàn),這和AP系統(tǒng)一直提供的一致性級(jí)別相類似,甚至更好。
理論上來(lái)說(shuō),將可用性從99.999%提升到99.9999%是不值得的(一年幾分鐘的差別),特別是在暫停期間接受寫的代價(jià)是永久的數(shù)據(jù)不一致。
結(jié)論
分布式事務(wù)是計(jì)算機(jī)科學(xué)領(lǐng)域最難解決的問(wèn)題之一。我們很幸運(yùn)地生活在這些系統(tǒng)現(xiàn)成的世界里。任何的有界一致性都比最終一致性要好,甚至拋開(kāi)其他遺留NoSQL的問(wèn)題,比如持久性,以及遺留的RDBMS問(wèn)題,比如運(yùn)維開(kāi)銷等等。
然而,除了Calvin之外,其他產(chǎn)品并不能實(shí)現(xiàn)沒(méi)有物理時(shí)鐘的分布式外部一致性。FaunaDB是唯一實(shí)現(xiàn)了類似Calvin事務(wù)協(xié)議的產(chǎn)品。我推薦你注意你的數(shù)據(jù)庫(kù)系統(tǒng)所提供的一致性保障,并嘗試一下使用FaunaDB。
本文作者
Evan Weaver是Twitter的前任基礎(chǔ)設(shè)施總監(jiān),他的團(tuán)隊(duì)負(fù)責(zé)擴(kuò)展Twitter的后端。他擁有計(jì)算機(jī)科學(xué)碩士學(xué)位,之前在CNET和SAP工作過(guò)。他是FaunaDB的聯(lián)合創(chuàng)始人。
查看英文原文:Back to the Future with Relational NoSQL
總結(jié)
以上是生活随笔為你收集整理的用关系型NoSQL回到未来的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 终极对决!Dubbo 和 Spring
- 下一篇: Pure-ftpd搭建FTP