資料庫大體分為以下幾類,有關係型(事務型)的資料庫,以oracle、mysql為代表,有keyvalue資料庫,以redis和memcached db為代表,有文檔型資料庫如mongodb,有列式資料庫以HBase,cassandra,dynamo為代表,還要其他的圖形資料庫、對象資料 庫、xml資料庫等。
有些資料庫本身就是分布式的資料庫設計理念,比如上面的列式資料庫;有些本身是單節點的設計架構,如redis、mongodb、關係型資料庫;
但是考慮到整個系統的可用性,這麼記憶體型的資料庫都有分布式部署的機制,如redis的主從複製,mongodb的Master-slave,replicaset,mysql和oracle的主從結構。
這裡提到老生常談的CAP原理,在分區的情況下,可用性和一致性只能保證一個,也就是在分布式的情況下,保障最終一致性(BASE)。
下面簡單總結一下
1、資料分布的模式
a、主從複製
主從模式是最常用的一種模式,從機儲存有主的全量數量,常用在主提供寫,多個從提供讀的情境。主從資料的一致性,可以實現為強一致,也可以實現為最終一致,具體看應用的具體要求(一致性和可用性的折中)。
基於弱一致性的情境中,考慮可用性的要求,採用非同步記錄日誌的方式,如mysql中的replication機制的binlog,oracle的archive log,mongodb中的oplog等。
b、sharding機制
當單個節點無法承載所有的資料量時,需要對資料進行切分,也就是sharding機制,資料的切分有很多種如concurrent hash,以及自訂的路由策略。
一致性hash,優點是資料節點的加入和退出,受影響的資料的範圍比較小。要考慮加入節點和節點宕機時,資料的遷移;當然基於可用性的考慮,在資料切分的基礎上,需要資料的多個備份。採用了Hinted Handoff的技術,用來保證在有節點故障後系統的寫操作不受太大影響。為了資料的均勻分布,可以把每個物理節點虛擬成多個邏輯節點,以邏輯節點作為環上的節點。節點的健康探測,可以基於gossip,也可以基於zookeeper進行管理維護。dynamo和cassandra中資料的切分分布是利用一致性hash。
自訂路由策略,可以設定主節點對資料進行路由,可以基於表的資料規則,如日期,或者連續的定界分割;對於節點的遷入和遷出,需要路由節點自己維護,並且由主節點對資料進行遷移,節點健康狀態由主節點(或者zookeeper)進行維護。HBase中的資料分布就是定義了一個META表,涵蓋了key的範圍所在分區,就是類似這種策略。
c、多主模式
多主模式在平時用的不多,且資料的一致以及衝突,資料的合并比較複雜,這裡不做闡述
2、一致性的解決方案
a、強一致性:
R+W>N,建設有3個節點,每次讀時,讀2個節點並且資料一致;寫時,寫2個節點都成功才算寫成功。這種是強一致性。
2PC,3PC 多個節點都成功時,才算成功,否則進行復原操作。
PAXOS,類似於2PC,解決分布式系統如何就某個值(決議)達成一致,進行投票選舉。是一種無主的節點的演算法。分布式的協調服務zookeeper就實現了這個演算法,保障一致性。mongodb中的叢集方案replicaset也實現了類似的演算法。
b、 弱一致性(最終一致):
由於分布式系統在資料同步時的網路延遲等等因素,無法保證副本資料和主節點時刻保持一致,當出現不一致的時,可以採用以下幾種策略保證最終一致性
Gossip(Cassandra,Dynamo),是帶冗餘容錯演算法,也就是最終一致性的演算法,無法保證某時刻所有節點資料一致,它是一個去中心化的部署方式,叢集中每個節點維護一組狀態,狀態可以用key,value,外帶一個版本號碼表示,版本大的比版本小的資料新,節點之間相互交流資料的版本資訊,並更新資料,類似病毒式的傳遞,這樣資料可以達到最終一致。Cassandra就是採取這種策略來進行資料的同步,並且維護節點的健康狀態。
向量時鐘(Dynamo),是一種資料不一致導致衝突的解決方案策略,系統採用樂觀鎖的策略,這樣對同一個值進行操作時,就可能會出現多個版本,由向量時鐘來解決一致性;每個元素是(更新值的節點,序號),每當更新一個值時,都帶上這些資訊,從可見,D3和D4出現資料的衝突,那麼在下次操作時,會由更新值的節點做衝突的解決。Dynamo採用的就是這種策略進行衝突的解決。
時間戳記(Cassandra),每次更新節點時,都帶上時間戳記資訊,衝突的解決以時間戳記最晚的為準。以Cassandra為代表。
Merle tree(Cassandra,Dynamo),在每個節點上針對每個區間裡的資料構造一棵Merkle Tree,這樣,在兩台節點進行資料比對時,從Merkle Tree的根節點開始進行比對,如果根節點一樣,則表示兩個副本目前是一致的,不再需要任何處理;如果不一樣,則遍曆Merkle Tree,定位到不一致的節點也非常快速,大大節省了比對時間以及資料的傳輸量。Dynamo和cassandra中的副本同步採用這種方案。