NoSQL 已死:我們不需要他了
作者:Rick Negrin是MemSQL的產(chǎn)品管理團隊負責(zé)人,他在微軟工作過12年,曾是SQL Server團隊的成員。
是時候承認我們早就知道的一個事實了:NoSQL 是并不適合許多現(xiàn)代應(yīng)用使用場景的工具,是我們該翻篇的時候了。
由于當時的數(shù)據(jù)庫無力處理所需的規(guī)模,NoSQL 技術(shù)應(yīng)運而生。這種新一代數(shù)據(jù)服務(wù)的興起解決了十多年前它問世時互聯(lián)網(wǎng)規(guī)模和數(shù)據(jù)迅速增加帶來的許多問題。NoSQL 還為冷存儲/偶爾批量訪問PB級數(shù)據(jù)提供了一條經(jīng)濟高效的新途徑。然而,因急于解決大數(shù)據(jù)和大量并發(fā)用戶帶來的難題,NoSQL 丟棄了數(shù)據(jù)庫的一些核心功能,而這些功能使得數(shù)據(jù)庫擁有高性能和易于使用的優(yōu)點。
進行這番取舍也許是NoSQL為數(shù)據(jù)庫領(lǐng)域做出的最大貢獻。NoSQL掀起了一場變革,集最佳的大數(shù)據(jù)功能與成熟關(guān)系模型的結(jié)構(gòu)和靈活性于一體,推出了一種易于擴展的關(guān)系數(shù)據(jù)庫。
關(guān)系數(shù)據(jù)庫不斷發(fā)展,打造了全新一代的系統(tǒng),可處理幾乎所有的工作負載,滿足現(xiàn)代應(yīng)用所需要的可擴展性、可靠性和可用性等要求。傳統(tǒng)的工作負載(比如事務(wù)應(yīng)用和業(yè)務(wù)分析)轉(zhuǎn)向比較新的工作負載(比如多租戶服務(wù)和操作分析)。Google Spanner、Azure Data Warehouse和 MemSQL,這些新的數(shù)據(jù)庫大行其道證明了這點:對于大多數(shù)使用場景而言,關(guān)系數(shù)據(jù)庫比 NoSQL系統(tǒng)更易于使用,性能通常更勝一籌。
我知道這可能會引起爭議,也知道你可能立馬覺得我的觀點有偏見。不過容我仔細介紹一下這種數(shù)據(jù)庫的歷史、架構(gòu)和應(yīng)用,之后你自行判斷也不遲。
NoSQL的崛起
NoSQL 在2000年代末大放異彩,不過它很早就問世了。它的出現(xiàn)主要是為了解決現(xiàn)有數(shù)據(jù)庫系統(tǒng)的規(guī)模問題。很顯然,橫向擴展(scale out)對于構(gòu)建大型系統(tǒng)而言是一種更經(jīng)濟高效的模式。對于谷歌、Facebook、微軟和雅虎構(gòu)建的超大電子郵件和搜索系統(tǒng)而言,這是擴展規(guī)模的唯一方式。
2007 年我讀了James Hamilton 介紹設(shè)計和部署大規(guī)?;ヂ?lián)網(wǎng)服務(wù)的一篇文章(https://www.usenix.org/legacy/event/lisa07/tech/full_papers/hamilton/hamilton_html/index.html)后,首次認識到了橫向擴展的價值。先是擴展應(yīng)用層,因為無狀態(tài)系統(tǒng)擴展起來比較容易。擴展存儲層是另一回事。根據(jù)定義,數(shù)據(jù)庫是有狀態(tài)的,跨分布式系維護該狀態(tài)的保證機制(即ACID)非常困難。于是在現(xiàn)有數(shù)據(jù)庫系統(tǒng)(比如MySQL和SQL Server 等)的上面構(gòu)建層,以創(chuàng)建一個分布式存儲層。
我在微軟的 SQL Server 團隊擔(dān)任產(chǎn)品經(jīng)理期間碰到過這方面的幾個例子。第一個例子出現(xiàn)在微軟內(nèi)部:微軟構(gòu)建了Webstore,這是 Hotmail及相關(guān)服務(wù)使用的SQL Server上面的分片層。實際上,Webstore是構(gòu)建最終成為如今的Azure SQL Database的數(shù)據(jù)庫系統(tǒng)的動因。雖然Webstore笨拙,缺少許多核心功能,但它很管用,讓微軟既能夠針對所需的數(shù)據(jù)規(guī)模來擴展,又能夠獲得高可用性。但 Webstore 需要整個工程師團隊來構(gòu)建和維護。
2000年代中期,MySpace使用大量的SQL Server服務(wù)器來管理這個迅速壯大的網(wǎng)站。該公司的用戶增長非??欤刻煨枰黾有碌腟QL Server機器。運行所有這些SQL Server、并且跨這些系統(tǒng)進行查詢是一項非常復(fù)雜的工作,需要大批工程師來維護。
同樣的情況出現(xiàn)在了Facebook及其他公司,因為所有新興的科技巨頭都面臨擴展難題。
很顯然,由于用戶眾多、數(shù)據(jù)不斷增加,這些新的數(shù)字服務(wù)巨頭需要一種新的解決方案來獲取、管理和發(fā)掘數(shù)據(jù)。理想情況下,我們需要這樣的系統(tǒng):可直接提供單一接口,但又能橫向擴展到許多機器上,并擁有內(nèi)置的高可用性。
最終,大規(guī)模云服務(wù)(谷歌、Facebook、雅虎和微軟等)都自行構(gòu)建了定制的系統(tǒng),以滿足規(guī)模擴展需求。那些系統(tǒng)各不相同,但采用了同樣的基本思路,有的直接共享,而有的通過學(xué)術(shù)共享。最終,采用這些同樣思路的開源系統(tǒng)開始涌現(xiàn)出來,NoSQL浪潮方興未艾。
為了解決互聯(lián)網(wǎng)規(guī)模問題,NoSQL在幾個關(guān)鍵方面有悖于傳統(tǒng)數(shù)據(jù)庫。接下來讓我們看看為什么做出這些選擇。
最終一致性的性能和弊端
存儲系統(tǒng)有兩種模型:ACID和BASE。
ACID 代表原子性(Atomic)、一致性(Consistent)、隔離性(Isolation)和持久性(Durable)。它涵蓋了你從大多數(shù)關(guān)系數(shù)據(jù)庫獲得的保證。ACID 保證寫入操作必須等數(shù)據(jù)進入磁盤后才能向客戶端返回成功訊號。此外,如果你很在意持久性(即不丟失數(shù)據(jù)),你可以對數(shù)據(jù)庫進行配置,以便等到寫入操作通過網(wǎng)路傳輸?shù)搅硗饽撑_機器,數(shù)據(jù)同樣進入該機器的磁盤。因此保證了寫入數(shù)據(jù)的正確性,但降低了寫入速度方面的性能。
BASE是NoSQL系統(tǒng)所特有的,代表基本可用(Basically Available)、軟狀態(tài)(Soft State)和最終一致(Eventually Consistent)。由于應(yīng)用程序不必等待查看寫入是否持久化,寫入時可更快地確保最終一致性。一旦數(shù)據(jù)存儲系統(tǒng)收到寫入操作,但在持久化到磁盤或另一個機器之前,它會告知應(yīng)用程序?qū)懭氩僮鞒晒?,?yīng)用程序可以進入到下一個操作。因此你獲得了性能方面的優(yōu)勢,但面臨的風(fēng)險是無法看到剛寫入的數(shù)據(jù),或者數(shù)據(jù)在出錯情況下可能完全丟失。
最終一致性合理兼顧了持久性與可用性。如果貴公司與消費者互動,延遲對貴公司的收入又有直接影響(所有內(nèi)容、社區(qū)和商業(yè)應(yīng)用環(huán)境都面臨這個問題),你希望用戶界面(UI)有最快的響應(yīng)速度。如果你要擴大規(guī)模以支持數(shù)百萬的并發(fā)用戶,就無法容忍任何瓶頸。數(shù)據(jù)庫架構(gòu)中采用最終一致性帶來的缺點是偶爾丟失某人的帖子或評論,而這種風(fēng)險對于這些類型的應(yīng)用而言是可以接受的。
需要兼顧持久性與可用性的另一個例子是金融應(yīng)用。你不希望銀行使用最終一致性來存儲 ATM交易或股票銷售的結(jié)果。在這種情況下,用戶仍要求延遲基本為零,而銀行又不愿意接受未寫入到磁盤的交易。
最終一致性有一席之地,但并非始終是唯一的解決方案。數(shù)據(jù)系統(tǒng)的架構(gòu)師和開發(fā)員應(yīng)能夠選擇自己想要哪種級別的一致性。應(yīng)在使用環(huán)境層面而不是在平臺層面進行這種選擇。
走無模式道路
目前不清楚為什么NoSQL潮流中不見數(shù)據(jù)庫模式(schema)的影子。是的,早期很難構(gòu)建一個分布式元數(shù)據(jù)管理器以便跨分布式系統(tǒng)來維護模式以支持操作,比如添加列。因此,早期設(shè)計沒有模式不足為奇。但最終完全消除了模式,而不是后來設(shè)法添加模式。有人認為模式會降低敏捷性,這也可以理解。好的模式設(shè)計很困難,需要事先認真思考。情況迅速變化時,你不希望被模式所束縛。
但這是一個謬論。
誠然,沒有模式為負責(zé)將數(shù)據(jù)錄入到系統(tǒng)的工程師增強了敏捷性。然而,它把這個問題推給了數(shù)據(jù)的讀取者(即用戶),而用戶的數(shù)量通常高出一個數(shù)量級,而且數(shù)據(jù)寫入時常常不了解數(shù)據(jù)的狀態(tài)。這些用戶通常從數(shù)據(jù)中創(chuàng)造價值,因此應(yīng)面臨盡量少的障礙。
打個比方,設(shè)想一下圖書館聲稱廢除杜威十進分類法,只是把書扔到地上的一個大洞里,聲稱這是一種更好的分類法,因為圖書管理員要做的工作量少得多。半結(jié)構(gòu)化數(shù)據(jù)有時間和地點屬性,因為有時你事先不知道一些數(shù)據(jù)的結(jié)構(gòu),或者它是否稀疏。但如果你真的不知道任何進來的數(shù)據(jù)或數(shù)據(jù)是什么樣子,那么數(shù)據(jù)又有何啥用?
事實上,模式總是存在。數(shù)據(jù)對某人來說始終有意義。此人應(yīng)該花時間將該數(shù)據(jù)編碼到一個平臺上,以便下一個人可以使用。如果數(shù)據(jù)混合已了解的數(shù)據(jù)和迅速變化的數(shù)據(jù),那么將后者放到數(shù)據(jù)庫中的半結(jié)構(gòu)化列,然后搞清楚以后從中映射哪些列。15 年前,SQL Server和Oracle可以對XML執(zhí)行這項任務(wù)。MemSQL及其他許多現(xiàn)代數(shù)據(jù)庫現(xiàn)在可以對JSON數(shù)據(jù)執(zhí)行這項任務(wù)。文檔數(shù)據(jù)存儲(以及鍵/值)應(yīng)該是現(xiàn)代數(shù)據(jù)庫的一項特性,而不是產(chǎn)品的唯一功能。
面向查詢的非SQL語法
NoSQL數(shù)據(jù)庫設(shè)計中的這個決定遵循了無模式化原則。如果你沒有模式,那么丟棄SQL語法還算合理。此外,很難為單單一種設(shè)備構(gòu)建查詢處理器,而構(gòu)建分布式查詢處理器難得多。尤其是,如果你是開發(fā)員,想讓一個新的應(yīng)用程序啟動并運行起來,這種系統(tǒng)讓人覺得更容易。
MongoDB 在簡單安裝和首次體驗方面做得堪稱完美。但結(jié)果證明,關(guān)系模型非常強大。如果你根本不想回答“獲取id是2的對象”之外的任何問題,單單有g(shù)et和put函數(shù)就行。但是外頭大多數(shù)應(yīng)用程序到頭來需要的不止如此。這篇文章解釋了文檔數(shù)據(jù)庫的不足之處。
在稍復(fù)雜一點的任何系統(tǒng),你總是希望以不同于存儲數(shù)據(jù)的方式來查詢數(shù)據(jù)。具有諷刺意味的是,20世紀60年代發(fā)明了關(guān)系模型,就是為了解那個年代的數(shù)據(jù)存儲系統(tǒng)(IMS和Codasyl)存在的這個問題。擁有連接(join)功能的關(guān)系數(shù)據(jù)庫是取出數(shù)據(jù)的唯一合理方式。是的,一開始比較難,但比將所有數(shù)據(jù)都獲取到你的應(yīng)用程序中、自行創(chuàng)建連接容易得多。我看到客戶一次次地對NoSQL這么做,結(jié)果總是讓人抓狂。
許多這些NoSQL系統(tǒng)實現(xiàn)了主要目標。它們提供了單一接口的數(shù)據(jù)存儲系統(tǒng),可以橫向擴展到許多機器上,擁有內(nèi)置高可用性。雖然已取得了一定的成功,但NoSQL的采用還是遇到了阻礙。
這有幾個原因。性能是關(guān)鍵因素,尤其是在有服務(wù)級別協(xié)議(SLA)的情況下進行分析查詢時??晒芾硇允橇硪粋€原因,因為分布式系統(tǒng)管理起來特別難。但是阻礙NoSQL采用的最主要因素還是需要對人員重新培訓(xùn)。許多人原先接受的是關(guān)系數(shù)據(jù)庫方面的培訓(xùn)和教育。在過去這10年,NoSQL一直試圖讓關(guān)系數(shù)據(jù)庫人員改弦易轍,但收效甚微。所有NoSQL公司在產(chǎn)值500億美元的數(shù)據(jù)庫總共也僅占一小部分的市場份額。
雖然軟件工程師似乎喜歡NoSQL,但數(shù)據(jù)人員(數(shù)據(jù)庫管理員、數(shù)據(jù)架構(gòu)師和分析員)老大不情愿地進入NoSQL領(lǐng)域;想實現(xiàn)必要的規(guī)模,NoSQL又似乎是唯一的途徑。而這意味著他們要重新學(xué)習(xí)新的API、工具和生態(tài)系統(tǒng),扔掉多年來積累的成功方法、模式和資產(chǎn)。他們希望使用一種成熟的模型來做事情,希望在不影響系統(tǒng)持久性、可用性和可靠性的情況下仍可以擴大規(guī)模。
從NoSQL到NewSQL ——確保性能和規(guī)模,又沒有弊端
我們構(gòu)建MemSQL時,假設(shè)客戶喜歡關(guān)系數(shù)據(jù)庫的功能,又想要橫向擴展型系統(tǒng)的可用性和可靠性。我們的目標是讓客戶可以兩全其美。
MemSQL是一種支持事務(wù)和分析的分布式關(guān)系數(shù)據(jù)庫,可在商用硬件上橫向擴展。你可以獲得熟悉的關(guān)系模型、SQL 查詢語法和龐大的工具生態(tài)系統(tǒng),以及現(xiàn)代云原生系統(tǒng)的擴展性和可用性。
不妨對照一下NoSQL 系統(tǒng)的核心差異。
兼顧一致性和性能
MemSQL有一些旋鈕(knob),讓你可以在一致和性能之間進行適當?shù)募骖?。這種取舍始終不可避免,但如今你不必在平臺層面在這兩者進行選擇。你可以為合適的每個使用場景來進行選擇。
一致性vs性能并不是某個棘手的哲學(xué)命題,關(guān)鍵是哪個對你的應(yīng)用和需求更重要。MemSQL有兩個設(shè)置可以讓你對此進行調(diào)整。第一個設(shè)置讓你可以決定是否等待磁盤持久化。有一個內(nèi)存中緩沖區(qū),可以在事務(wù)被持久化到磁盤之前存儲事務(wù)。可以在數(shù)據(jù)一進入緩沖區(qū)就返回成功訊號,也可以在數(shù)據(jù)進入磁盤后返回成功訊號。如果進入緩沖區(qū)就返回,可能會在持久化之前出現(xiàn)機器故障或重啟,數(shù)據(jù)就會丟失。另一方面,等待數(shù)據(jù)持久化到磁盤要花更長的時間。
此外,如果是高可用性環(huán)境,有兩種復(fù)制模式:同步復(fù)制和異步復(fù)制,確保數(shù)據(jù)在另一臺機器上有第二個副本。如果你將復(fù)制設(shè)置為同步模式,你要等到輔助機器上收到事務(wù)后,才能將成功訊號返回給客戶端。如果使用異步復(fù)制模式,事務(wù)返回成功訊號之后,數(shù)據(jù)復(fù)制到輔助機器。這讓你能夠調(diào)整一致性和持久性,以獲得適合你風(fēng)險/性能具體要求的性能。
MemSQL 7.0包括快速同步復(fù)制和同步持久性
保持分布式系統(tǒng)中的模式
MemSQL實現(xiàn)模式的方式是,將元數(shù)據(jù)存儲在小型內(nèi)部數(shù)據(jù)庫中,元數(shù)據(jù)更改時就將元數(shù)據(jù)同步復(fù)制到所有節(jié)點。它使用兩階段提交來確保DDL更改在集群中正確地傳播,以一種不會阻塞選擇性查詢的方式來構(gòu)建。
不過MemSQL不僅僅支持關(guān)系模型。你可以輸入一個列作為JSON列,并存儲一個JSON 文檔。如果你覺得以后想要查詢幾個列,可以將屬性映射為列,并編制索引。MemSQL還支持空間類型和全文索引。我們明白,客戶需要在一個熟悉的系統(tǒng)中有混合類型的數(shù)據(jù),所有類型的數(shù)據(jù)都能自然地共存。
保留SQL“通用語”
MemSQL解決了在大規(guī)模環(huán)境下跨分布式數(shù)據(jù)庫使用SQL語法的問題。分布式查詢處理器讓你可以使用標準SQL語法來表達查詢,系統(tǒng)負責(zé)將查詢?nèi)蝿?wù)分配到集群中的各節(jié)點,并幫你匯總結(jié)果。MemSQL支持所有常見的ANSI SQL操作符和函數(shù),它們?yōu)槟闾峁┝丝杀磉_幾乎任何查詢的強大模型。
MemSQL通過系統(tǒng)中兩種類型的節(jié)點:匯聚器(aggregator)和葉子(leaf)來做到這一點。匯聚器節(jié)點處理分布式系統(tǒng)的元數(shù)據(jù)、路由查詢和聚合結(jié)果。葉子節(jié)點存儲數(shù)據(jù),并處理在分區(qū)上執(zhí)行查詢這項繁重任務(wù)。如果可以,MemSQL會在本地執(zhí)行連接,這表明了為何模式設(shè)計相當重要。如果不行,MemSQL將根據(jù)需要轉(zhuǎn)移數(shù)據(jù)。因此,客戶可以在不知道數(shù)據(jù)在底層如何分區(qū)的情況下使用SQL語言。
MemSQL跨匯聚器節(jié)點和葉子節(jié)點分發(fā)數(shù)據(jù)
這意味著借助MemSQL,你可以利用貴公司已有的技能、資源和工具,或者人們可以像使用其他關(guān)系數(shù)據(jù)庫那樣使用 MemSQL,不需要重新培訓(xùn)。此外,由于MemSQL支持MySQL連線協(xié)議,現(xiàn)有的龐大生態(tài)系統(tǒng)(包括BI、ETL及其他中間件工具)完全與MemSQL兼容。你沒必要雇用新的員工、學(xué)習(xí)一堆新工具或者引進新軟件。只管用就行。
向NoSQL說再見!
由于Web應(yīng)用和多租戶服務(wù)大行其道,NoSQL應(yīng)運而生,以滿足規(guī)模需求。想想解決這些問題的難度,就可以理解早期試圖在存儲層處理規(guī)模擴展的舉措為何迫使用戶作出艱難的取舍。
但關(guān)系數(shù)據(jù)庫迎來了發(fā)展。它們可以處理幾乎所有的工作負載,滿足現(xiàn)代應(yīng)用程序所需的可擴展性、可靠性和可用性等要求。
由于所有公司意識到數(shù)據(jù)驅(qū)動的價值,它們希望所有員工都能獲得最新的數(shù)據(jù)。為此,需要一種新的分析系統(tǒng),可以擴展規(guī)模以支持成百上千的并發(fā)查詢、不需要預(yù)先聚合就可以快速查詢,并且在數(shù)據(jù)創(chuàng)建時實時獲取數(shù)據(jù)。除此之外,它們希望向客戶和合作伙伴敞開數(shù)據(jù),這需要切實可行的SLA、安全功能、性能和規(guī)模,而目前的數(shù)據(jù)存儲系統(tǒng)卻滿足不了這個要求。幾種新的工作負載促使企業(yè)需要遺留數(shù)據(jù)庫和NoSQL系統(tǒng)無力提供的新功能,操作分析之類的工作負載只是其中之一。
關(guān)系模型經(jīng)受住了時間的考驗,它在不斷添加新的創(chuàng)新。此外,它吸納了新的數(shù)據(jù)類型 (搜索、空間和半結(jié)構(gòu)化數(shù)據(jù)等)和一致性模型,那樣各種數(shù)據(jù)就可以在一個系統(tǒng)中共存。關(guān)系模型或SQL查詢語法沒有固有的可擴展性難題。它只要不同的存儲實現(xiàn)方法,就可以充分利用橫向擴展型架構(gòu)。
MemSQL等新的數(shù)據(jù)庫已證明,對于大多數(shù)使用場景而言,關(guān)系數(shù)據(jù)庫更容易使用,通常性能比NoSQL系統(tǒng)更勝一籌。
謝謝你,NoSQL。你對數(shù)據(jù)庫社區(qū)施加了壓力,迫使社區(qū)解決云規(guī)模領(lǐng)域的難題。NoSQL很管用。然而,關(guān)系數(shù)據(jù)庫取得了發(fā)展,可以滿足那些要求。我們已進入到下一個階段。