Master-slave 架構能夠說是最經常使用的架構,關係型數據庫諸如:mysql,postgreSql,oracle,Nosql諸如:MongoDb,消息隊列諸如:Kafka,RabbitMQ等都使用了這種架構,本文將先簡要介紹此種架構並介紹高可用Master-slave架構中的一些坑,以及應對之策。mysql
因此一般狀況下,這種架構通常都是用徹底異步的方式進行同步,這種狀況下,若是主庫失效,那麼全部尚未被複制的數據就可能會被丟失;可是若是從庫失效,主庫依然能夠繼續處理寫入操做。web
主庫會記錄每一個請求的sql,而且將這些sql:insert select update等發送至從庫執行,雖然聽上去沒什麼問題,可是:redis
這種複製方法如今基本不太使用了。算法
以前說過,主庫在處理寫請求時,都會先寫WAL(Write Ahead Log),日誌的結構很是底層,包含了寫入時須要追加的數據序列:磁盤塊中哪些數據發生了更改。這就意味着它會比數據庫存儲結構緊密相關,甚至有可能數據庫只由於版本不一致而致使沒辦法複製。sql
對於運維來講,這點就很不友好了。若是複製協議對於版本不匹配的話,一般狀況下須要停機才能夠升級。數據庫
另外一種方法是使用另外一種日誌,只是這種日誌再也不於底層存儲耦合,好比Mysql的binlog。它通常是以行爲密度來描述寫入的操做:緩存
這種日誌普遍應用,它包含的信息與底層徹底解耦,甚至能夠基於它複製不一樣數據庫的數據。微信
若是咱們須要新增新的副本,如何保證新的從庫擁有與主庫徹底一致的數據呢?由於客戶端在不斷的向主庫寫入數據,最簡單的辦法,咱們能夠禁止主庫的寫入,而後使用日誌進行同步;但這會違背咱們高可用的原則。咱們通常使用以下方法:網絡
首先每一個從庫的硬盤上確定也會記錄全部從主庫收到的數據庫的變動,若是從庫掛了,等他恢復的時候能夠從日誌中知道發生故障以前最後處理的一個事物,接着鏈接主庫,請求拉取全部以後它斷片以後數據變動,以後追遇上主庫便可架構
主庫掛了須要fail over(故障轉移):須要將一個新的從庫提高爲主庫,而且從新配置應用客戶端,將全部寫操做發送到新的主庫。一般有以下幾個步驟:
一、確認主庫失效。現實生活中有不少緣由致使失效:崩潰、停電、網卡以及機器被修空調的師傅搬走等緣由。沒有萬無一失的方法,大部分系統採用簡單的超時來肯定。
二、選一個新的主庫。主庫的選舉一般是以擁有着主庫最新數據的那個從庫爲準,具體的算法能夠是paxos raft等共識算法。
三、從新配置路由,寫請求發送到新的主庫上;而且若是老領導回來了,須要避免「腦裂」的狀況,讓老領導下臺成從庫。
failOver一樣會有不少問題:
大部分web應用都是讀多寫少,因此咱們一般採用多副本異步複製的架構,基於異步架構,可能會致使數據庫從庫和主庫的明顯不一致,可是通過一段時間後,他們最終會是一致的。
正常狀況下,複製延遲大概是幾分之一秒,可是在極端的狀況下(網絡延遲,機器高負荷)延遲可能達到幾秒甚至幾分鐘。
因此這是咱們在實際中會遇到的真實問題,瞭解這些問題以後能夠幫助咱們更好的設計業務。問題體如今下面幾個方面:
讀寫一致性的意思就是保證用戶能夠讀到本身的寫,可是不保證其它用戶也能夠及時的讀到;其它用戶可能須要延遲才能夠讀取到。保證讀寫一致性的話,有下面幾個方向:
還有一種狀況,好比用戶有電腦和app端進行查詢,電腦更新了信息如何保證手機上能夠及時的查看到,如何保證讀寫一致性呢?有多臺設備的話你沒法記錄末次更新的時間戳(由於手機不可能知道電腦末次操做的時間),不一樣設備的時間自己也是不可靠的,這種狀況,能夠根據userID進行散列,保證同一個用戶永遠會落到一個Datacenter上的主庫。
單調讀的意思是時光倒流:
用戶2345前一秒還能夠查詢出結果,後一秒數據就沒有了。單調讀是這種異常的保證機制,咱們須要保證同一個用戶的查詢請求老是被落到同一個follower上,好比說能夠根據userid取模,散列到固定的機器上。
實際上數據庫的操做能夠分紅因果操做和併發操做兩種類型,併發操做能夠理解爲A發起set A操做,B發起set B操做,這兩個操做是併發的沒有前後因果關係的,數據庫對於這種操做只須要確認發生的順序就能夠肯定最終的值;對於因果操做:A發起insert 666,B再發起update 666,這兩個操做是有依賴關係的,A成功了B才能夠成功。若是數據庫先接受到B的請求,那麼久發生衝突了。 這樣的操做叫作因果操做。(下一章會詳細討論)
回到咱們的問題,若是要解決這類問題,首先咱們須要一個算法分辨出那些操做是併發的,那些操做是因果的;對於這種問問題再回答的典型的因果類型的操做,咱們應該儘可能讓他們分配到同一個partition以內,確保有因果關係的寫入到寫到同一個分區。
本文討論了典型的master-salve架構中常見的問題和解決的辦法,某些概念尚未進行深刻研究,後續介紹多主、無主架構時再說明。
根據CAP原則,最終一致性是無可避免的,可是咱們能夠作一些基於業務的特殊處理,在保證高可用的同時,儘可能去保證數據的一致性。