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