?譯者 | 陳峻
審校 | 孫淑娟
在過去的十年間,分布式系統已遍布全球。它們跨區域地使用編排技術,實現了橫跨多個云服務提供商及本地基礎設施的混合云式部署,負載平衡,以及高可用性。在此基礎上,數據庫領域也在不斷迭代與發展。近年來,業界大量涌現了專為分布式數據庫部署而設計的新型數據庫系統。當然,也有部分數據庫已在原有的設計中,添加了分布式架構組件。
DB-Engines.com評出的百強數據庫
知名網站DB-engines.com使用加權算法,跟蹤了各種數據庫在各個平臺上的提及次數、Google的搜索趨勢、Stack Overflow上的討論頻率、推文發布的職業技能次數、以及LinkedIn個人資料出現的數量。下圖展示了截至2022年5月,在上榜的394種數據庫中,市場占比前100的數據庫分布情況。
截至2022年5月,DB-Engines.com上排名前100的數據庫
其中,作為傳統的SQL系統,關系數據庫管理系統(RDBMS)仍占比最大,高達47%。而占比25%是NoSQL系統,涵蓋了豐富的類型,包括:MongoDB之類的文檔數據庫、Redis之類的鍵值系統、ScyllaDB之類的寬列(wide column)數據庫、以及Neo4j之類的圖形數據庫。而占比11%的“多模型”數據庫包含了在同一系統中,同時支持SQL和NoSQL的混合體(如:Microsoft的Cosmos DB和ArangoDB),或支持多種NoSQL數據模型的數據庫(如:DynamoDB,它將自己列為NoSQL鍵值系統和一個文件存儲的集合)。
什么是分布式數據庫?
人們對于如何構建符合SQL(源自ANSI/ISO/IEC9075:2016的正式標準化)的分布式RDBMS系統有著不同的理解。目前ANSI、ISO、IETF或W3C尚未對“NoSQL數據庫”進行明確的定義。在我看來,分布式數據庫的基本特征是:首先定義了一個集群,并在其中分布了不同的數據;接著,集群中定義了各個節點角色。每個節點或是對等節點,或是有某些節點處于領導位置,而其他節點扮演跟隨者的角色。然后,這些角色能夠實現彼此的故障轉移。最后,它們能夠盡可能地均勻復制和分片數據。
在此基礎上,我們可以從上述名列前100名的數據庫中,挑選出5種典型的,并將它們分為如下兩類:
SQL+NewSQL | NoSQL |
PostgreSQL | MongoDB |
CockroachDB | Redis |
| ScyllaDB(Cassandra) |
在上表的左側,Postgres和CockroachDB代表了分布式SQL。其中,CockroachDB號稱“NewSQL”,是專為分布式數據庫而設計的。在上表的右側,MongoDB、Redis和ScyllaDB都屬于分布式NoSQL。總地說來,如果您需要表聯合(JOIN)操作的話,可以沿用SQL和RDBMS。如果您需要對數據進行非規范化,那么便可以選擇NoSQL。
多數據中心集群
前面提到了集群的概念。早在多數據中心的設計架構被提出之前,PostgreSQL、MongoDB和Redis都被設計為單數據中心的本地集群。
- 如上表所示,首發于1986年的Postgres,完全早于云計算的概念。但隨著時間的推移,它在設計和功能上發生了不少的改進。
- 作為NewSQL的代表,CockroachDB在設計之初就考慮到了全局性分布。
- MongoDB在公有云誕生之初發布,其最初的設計只考慮到了單個數據中心集群,現在也增加了對于各種不同拓撲的支持。使用MongoDB Atlas,您可以非常輕松地將其部署到多個區域中。
- 根據低延遲的設計理念,Redis通常被部署在單個數據中心中。同時,它也提供了允許部署多數據中心的企業功能。
- ScyllaDB和Cassandra一樣,從一開始就在設計中考慮了多數據中心的部署。
集群
在分布式數據庫的概念中,我們提到了復制和分片。這完全取決于數據庫架構的分層或同構程度。例如,MongoDB只有一個主節點,其余都是該主節點的副本(被稱為副本集)。您只能在主節點上寫入數據庫。而由于副本為只讀,因此您無法直接更新它們,而必須由主節點去更新其他副本。顯然,這些節點是異構的,而不是同構的。
這類主備(Primary-Replica)架構有助于在重讀取(read-heavy)的工作負載中分配流量。而在混合或重寫入(write-heavy)的工作負載中,主節點會成為瓶頸。也就是說,在主節點出現故障時,由于集群需要臨時選出一個新的主節點,因此數據庫會不得不臨時暫停寫入操作。這就是所謂的單點故障。
相反,ScyllaDB和Cassandra屬于“無領導”的P2P多活(Active-Active)系統。由于客戶端可以讀取或寫入任何同構的節點,因此避免了單點故障。也就是說,每個節點都可以更新集群中任何其他副本的數據。
可見,雖然多活會帶來更多的計算量,但是它解決了服務器保持彼此同步的問題。用戶最終會得到一個適合重寫入的負載平衡的系統,畢竟每個節點都可以提供讀取與寫入服務。
下面,我們看看上述5種數據庫在主副本和P2P多活方面的表現:
- CockroachDB和ScyllaDB(以及Cassandra)是按照多活模式設計的。
- Postgres需要一些外部方法來實現多活,而并非內置。
- MongoDB并不支持多活。
- 在Redis企業版中,我們可以使用無沖突的復制數據類型(conflict-free replicated data types,CRDT)來實現多活模式。
注意,Postgres、MongoDB和Redis都默認會使用主副本的數據分布模式。
復制
分布式系統設計也會影響到已部署的不同機架、或數據中心之間分配數據的方式。例如,在一套給定主副本系統中,只有擁有主節點的數據中心,才能服務于任何寫入的負載。而其他數據中心只能作為只讀副本。
而在支持多數據中心集群的對等系統中,整個集群中的每個節點都可以接受讀取或寫入負載。顯然,這會更方便將工作負載分布到多個地理位置。
例如,通過使用ScyllaDB,您可以判定每個站點具有相同甚至不同的復制因子。在上圖的右側,我們展示了在一個數據中心擁有三個數據副本,而在另一個數據中心擁有兩個副本的情況。
不同級別的操作會具有一致性。您可能在具有三節點的數據中心進行本地的“仲裁”式讀取或寫入(即:需要通過本地仲裁來更新三個節點中的哪兩個)。當然,您也可能有一個集群范圍內的仲裁,判定需要更新一個或兩個數據中心里的任意三個節點。
拓撲感知
我們已經了解了分布式數據庫的本地集群方式,它可以有效地讓多個系統分擔負載。您也可以跨多個地域節點對數據庫進行分片,或是通過確保相同數據在多個節點上的高可用性,來保證數據的復制。
下面,讓我們假設一個場景:如果您的所有節點都安裝在同一個機架中,而整個機架出現了故障,那該怎么辦呢?此時,我們需要用到同一數據中心內的機架拓撲感知,以確保將數據分布到該數據中心的多個機架中,從而最大限度地減少因電源或網絡中斷,而導致的整個機架與另一個機架失去連接。
在分布式數據庫中,我們需要數據庫的多個副本,運行在不同的數據中心上,以實現跨集群的更新機制。每個單一數據庫都能夠自主運行,而且它們的同步機制既可以是單向的(由一個數據中心去更新下游副本),也可以是雙向或多向的。這種地理分布可以通過允許就近用戶的連接,來最小化延遲,進而確保在出現單個數據中心的災難時,用戶不會丟失部分甚至全部數據。
下面,我們來看看上述5種數據庫在拓撲感知方面的表現:
- CockroachDB和ScyllaDB均有內置的拓撲感知特性。
- MongoDB從2015年后開始引入拓撲感知特性。
- Postgres和Redis最初被設計為單數據中心方案。雖然不是開箱即用的,但是您可以像添加多活功能那樣,去手動添加拓撲感知服務。
下面,我們根據上述各項分布式特點,對5種數據庫進行屬性上的總結和對比。
PostgreSQL
Postgres是如今最流行的SQL實現之一。它提供了開箱即用的本地集群。不過,由于Postgres仍在致力于完善其多數據中心的集群,因此您需要通過額外的配置和開發,方可實現。
由于SQL建立在高度一致的事務性模式上,因此它不適合廣泛地跨越地理區域的集群。每個查詢都會被所有相關數據中心之間的長時間延遲而放大。
同時,Postgres依賴于主副本模型。集群中存在著主節點和副本節點的關系。您也可以額外地添加負載均衡器,或者多活附加組件。此外,Postgres雖然在自動化分片方面取得了一些進展,但是目前仍需要用戶進行手動數據分片。
CockroachDB
作為“NewSQL”的CockroachDB不但使用了Postgres的傳輸協議(wire protocol),而且大量借鑒了許多由Postgres開創的概念。當然,它并沒有局限于Postgres架構。例如:多數據中心集群和對等無領導拓撲,都被內置了進去。
此外,CockroachDB不但具有自動分片和數據復制功能,而且也內置了數據中心的感知能力,您可以按需添加機架的感知功能。
值得注意的是,由于CockroachDB需要所有的事務具有高度一致性,因此用戶喪失了最終一致性或可調一致性(Tunable Consistency)的靈活度。這不但會降低吞吐量,而且會在任何跨數據中心的部署中,產生高基線的延遲(high baseline latencies)。
MongoDB
作為NoSQL典型代表的MongoDB,已被開發出了許多分布式數據庫功能。例如,它已經能夠實現多數據中心的集群了。雖然MongoDB在大多數情況下,仍然需要遵循主副本模式,但有用戶可以通過第三方工具使其實現P2P的多活模式。
Redis
作為“鍵值對”存儲的典型數據庫,Redis旨在實現內存緩存或數據存儲。雖然它可以持久化數據,但是如果數據集不適合內存的話,就會讓性能大打折扣。
Redis在設計上默認考慮了本地集群。這會導致例如:一旦您無法在5毫秒內從SSD獲取數據,就無法在145毫秒內完成從舊金山到倫敦的網絡傳輸往返時間。當然,對于那些確實需要多地域分布存儲的企業而言,它們仍然會在多數據中心里構建Redis集群。
同時,由于Redis往往是作為主副本模式運行的,因此它更適用于重讀取的緩存服務器。也就是說,它需要數據被先寫入,然后再分散到副本處,以平衡它們的緩存負載。
Redis的企業功能可以實現P2P的多活集群。同時,Redis能夠自動分片和復制數據。不過,其拓撲感知功能僅限于帶有企業特性的機架感知。
ScyllaDB
ScyllaDB是按照Apache Cassandra的分布式數據庫模型設計的。默認情況下,它帶有多數據中心集群,而且采取的是無領導的多活拓撲。
ScyllaDB會自動分片,并為每個操作提供了可調的一致性。如果您想獲得更強的一致性,它也能夠支持輕量級事務,并提供寫入的線性化。
就拓撲感知而言,ScyllaDB支持機架感知和數據中心感知。它甚至支持令牌感知和分片感知,ScyllaDB不僅可以知曉該在哪個節點存儲數據,而且可以獲悉與該數據關聯的CPU信息。
小結
在上文中,我們分析了五種知名的分布式數據庫系統。其中,CockroachDB為SQL數據庫提供了開箱即用的特性與屬性的全面組合,而ScyllaDB為NoSQL系統提供了全面的功能。目前,分布式數據庫仍在不斷迭代與改進。它們正變得更加靈活、更具可擴展性、以及具有更高的性能。
譯者介紹
陳峻 (Julian Chen),51CTO社區編輯,具有十多年的IT項目實施經驗,善于對內外部資源與風險實施管控,專注傳播網絡與信息安全知識與經驗;持續以博文、專題和譯文等形式,分享前沿技術與新知;經常以線上、線下等方式,開展信息安全類培訓與授課。
原文標題:??Comparing Distributed Databases???,作者:Peter Corless?