關係型數據庫到底有什麼問題?數據庫
正如不少人可能已經知道的,關係型數據庫(RDB)技術自從1970年代就已經存在,直到1990年代末一直是結構化存儲的事實標準。RDB幾十年來很出色地支持了高度一致性事務的工做負載,並依然保持強勁。隨着時間的推移,該項古老的技術爲應對客戶的需求得到了新的能力,好比BLOB存儲、XML/文檔存儲、全文檢索、在數據庫中執行代碼、使用星形數據結構的數據倉庫、以及地理空間擴展。網絡
只要一切都能擠進關係型數據結構的定義中,而且適合於單機,就能夠在關係型數據庫中實現。數據結構
然而,互聯網的商業化發生了,而且完全改變了一切,使得關係型數據庫再也不可以知足全部的存儲需求。相比於一致性,可用性、性能和擴展正在變得一樣重要——有時甚至更重要。異步
性能一直很重要,可是隨着互聯網商業化的出現,改變的是規模。事實證實,要達到規模化的性能,要求的技巧和技術是前互聯網時代沒法接受的。關係型數據庫圍繞着ACID(原子性Atomicity、一致性Consistency、隔離性Isolation和持久性Durability)的概念而創建,實現ACID最簡單的方法就是把一切保持在單機上。所以,傳統的RDB規模化的方法是垂直擴展(scale up),用白話說,就是使用更大的機器。分佈式
哦-哦,我想我須要一臺更大的機器。oop
使用一臺更大的機器的解決方案一直很好,直到互聯網帶來的負載大到單機沒法處理。這迫使工程師們想出巧妙的技術來克服單機的限制。有許多不一樣的方法,各有其優缺點:主—副、集羣、表聯合與分區(table federation and partitioning)、水平分區(sharding,能夠認爲是分區的特例)。性能
致使數據存儲選項增長的另一個因素是可用性。大數據
前互聯網時代的系統,其用戶一般是來自組織的內部,這就有可能在非工做時段設置有計劃的停機時間,甚至計劃外的宕機也只會形成有限的影響。商業化互聯網也改變了這一點:如今每一個可以訪問互聯網的人都是潛在用戶,因此計劃外的宕機會形成極可能更大的影響,並且互聯網的全球性致使很難肯定非工做時段,並安排有計劃的停機。優化
我曾探討了冗餘在實現高可用性中所起的做用。不過,當應用到數據存儲層時,冗餘帶來了一系列新的有趣的挑戰。在數據庫層應用冗餘最經常使用的方式是主/副配置。網站
這個看似簡單的設置,在與傳統的單機關係型數據庫比較時,有一個巨大的差別:咱們如今有網絡隔離的多臺機器。當數據庫的寫操做發生時,咱們如今要決定什麼時候認爲它完成了:只要保存到主數據庫,或者只要保存到副數據庫(或者甚至是n個副數據庫,若是咱們想要得到更高的可用性--欲知增長另外一臺機器對整個可用性的影響,請參看本博客系列的第一部分)。若是咱們決定保存到主數據庫就足夠了,在複製數據以前若是主數據庫失效,咱們要承擔丟失數據的風險。若是咱們決定等到數據複製完成,咱們就要接受延遲的代價。在副數據庫宕機的罕見狀況下,咱們須要決定是繼續接受寫操做的請求,仍是拒絕它。
所以,咱們從一個默認一致性的世界,進入了一個一致性是一種選擇的世界。在這個世界裏,咱們能夠選擇接受所謂的最終一致性,即,狀態在多個節點之間複製,可是並不是每一個節點都有整個狀態的完整視圖。在咱們上面的示例配置中,若是咱們選擇認爲達到主數據庫就是寫操做完成(或者到達主數據庫和任一副數據庫,但不必定是兩個副數據庫),那麼咱們就是選擇了最終一致性。最終,由於每一個寫操做會被複制到每一個副數據庫。可是在任一時間點,若是咱們查詢某一個副數據庫,咱們沒法保證它包含截止到那個時刻爲止的全部寫操做。
CAP理論
總而言之,當數據存儲被複制(也稱爲分隔(partitioned))時,系統的狀態被分散。這意味着咱們離開了溫馨的ACID領域,進入CAP的美麗新世界。CAP理論是由加州伯克利分校的Eric Brewer博士在2000年提出的。它最簡單的形式是這樣的:一個分佈式系統必須在一致性、可用性和分隔容忍度(Partition Tolerance)之間取捨,而且只能作到三者中的二者。
CAP理論把關於數據存儲的討論擴展到超出ACID的範圍,激發了許多非關係型數據庫技術的誕生。在提出他的CAP理論的10年以後,Brewer博士發表了一份聲明,澄清他最初的「三選二」的觀點被極大地簡化,是爲了引發討論,並有助於超越ACID。不過,這種極大的簡化,引起了無數的曲解和誤會。在對CAP更精細的解釋中,全部三個維度應當理解爲範圍,而不是布爾值。此外,應當理解,分佈式系統大部分時間工做在非分隔模式,在這種狀況下,須要作出一致性和性能/延遲之間的折中。在分隔真的發生的罕見狀況下,系統必須在一致性和可用性之間作出選擇。
聯繫到咱們以前的主/副例子,若是選擇認爲只有當數據在全部地方被複制(也稱做同步複製)以後寫操做纔算完成,咱們就是以寫操做延遲爲代價選擇了一致性。另外一方面,若是選擇認爲一旦數據保存到主數據庫中,就認爲寫操做完成,並讓複製在後臺進行(也稱做異步複製),咱們就是以犧牲一致性爲代價選擇了性能。
當網絡分隔發生時,分佈式系統進入特殊的分隔模式,在一致性和可用性之間取捨。回到咱們的例子:多個副數據庫在失去與主數據庫的鏈接以後,可能仍然繼續提供查詢服務,就是以犧牲一致性爲代價選擇了可用性。要麼,咱們能夠選擇,主數據庫若是失去與副數據庫的鏈接,就應當中止接受寫操做的請求,所以就是以犧牲可用性爲代價選擇了一致性。在商業化互聯網時代,選擇一致性一般意味着收入的損失,因此不少系統選擇可用性。在這種狀況下,當系統恢復到正常狀態時,它能夠進入恢復模式,全部積累的不一致性獲得解決和複製。
趁咱們還在談論恢復模式,值得說一說一種稱爲主—主(或主動—主動)的分佈式數據存儲配置。在這種設置中,寫操做能夠發送到多個節點,而後再互相複製。在這樣的系統中,即便是正常的模式也變得複雜了。由於,若是對同一條數據的兩個更新在大體相同的時間發生在兩個不一樣的主節點上,要如何協調呢?不只如此,若是這樣的系統不得不從一個分隔的狀態恢復,事情就變得更糟了。雖然有可能存在可行的主—主配置,並且也有一些產品使之更容易,個人建議是除非絕對必要,不然儘可能避免。有不少方法能夠實現性能和可用性的良好平衡,而沒必要須要負擔主—主配置的高複雜度性的成本。
許多現代數據存儲的常見模式
提供的性能/規模和可用性良好搭配的一種常見方法,是結合分隔和複製造成一種配置(或者說是模式)。這有時被稱爲分隔的副本集合(partitioned replica set)。
不管是Hadoop、Cassandra或者MongoDB集羣,全部這些基本上都符合這種模式,許多AWS數據服務也是如此。讓咱們瞭解一下分隔的副本集合的一些共同特徵:
數據是跨多個節點(或者多個節點集羣)分隔的(即,分開的)。沒有單一分區擁有全部的數據。單個寫操做只發送到一個分區。多個寫操做有可能發送到多個分區,所以應當彼此獨立。複雜的、事務性、多條記錄(所以可能涉及多分區)的寫操做應當避免,由於這樣可能影響整個系統。
單個分區可以處理的最大數據量可能成爲潛在的瓶頸。若是一個分區達到它的帶寬上限,增長更多的分區以及拆分橫跨其間的流量,有助於解決該問題。所以,能夠經過增長更多的分區來擴展這種類型的系統。
一個分區的索引(key)用來分配各個分區的數據。你須要當心選擇分區的索引,這樣讓讀操做和寫操做盡量平均「分佈」在全部的分區。若是讀/寫操做發生彙集,這些操做可能超出某個分區的帶寬,進而影響整個系統的性能,而其它分區則並未充分利用。這被稱爲「熱分區」問題。
數據在多臺主機之間複製。這能夠是,每一個分區是徹底分開的副本集合,或者在同一組主機之上的多個副本集合。一條數據被複制的次數一般被稱爲複製因子。
這樣的配置擁有內置的高可用性:數據被複制到多個主機。理論上,若干小於複製因子數量的主機發生故障,不會影響整個系統的可用性。
全部這些好處,以及內置的可擴展性和高可用性,伴隨着相應的代價:這再也不是你的瑞士軍刀,單機的關係型數據庫管理系統(RDBMS)了。這是複雜的系統,有不少須要管理的可變更的部分和須要微調的參數。須要專業知識來設置、配置和維護這些系統。此外,須要監測和報警的基礎設施來確保它們的正常運做。你固然能夠本身作,但不容易,你可能短期沒法搞定。
豐富的數據存儲,雖然引發一些選擇困難,但實際上是好事。咱們只需超越傳統的整個系統只有單個數據存儲的想法,接受系統中使用多種數據存儲、每一個爲它最適合的工做負載提供服務這樣的思惟方式。例如,咱們可使用下面的組合:
高性能攝入隊列,來獲取輸入點擊流量
基於Hadoop的點擊流量處理系統
基於雲的對象存儲,用來低成本、長期地存儲通過壓縮的平常點擊流量摘要
保存元數據的關係型數據庫,可供咱們用於充實點擊流量的數據
用於分析的數據倉庫集羣
用於天然語言查詢的搜索集羣
上面全部這些均可以是某個單一子系統的組成部分,好比叫作網站分析平臺。
總結
商業化互聯網帶來擴展和可用性的需求,而RDBMS這樣的瑞士軍刀再也沒法知足這樣的需求。
對數據存儲增長水平擴展和冗餘加大了系統複雜度,使得ACID更加難以保證,迫使咱們按照CAP理論考慮取捨,創造了許多優化和專業化的有趣機會。
在系統中使用多個數據存儲,每一個爲與其最適當的工做負載提供服務。
現代數據存儲是複雜的系統,要求特殊的知識和管理開銷。