在高并發場景下,資料主從同步是必然的方式,除了資料庫主從同步外,還會涉及到分布式環境下的資料同步。
今天分享資料庫主從同步解決方案@mikechen
資料主從同步的由來
網際網路的很多業務,特别是在高并發的場景下,基本都是讀遠遠大于寫,如果資料庫讀和寫的壓力都同在一台主機上,這顯然不太合理。
于是,把一台資料庫主機分為單獨的一台寫主庫(主要負責寫操作),而把讀的資料庫壓力配置設定給讀的從庫,而且讀從庫可以變為多台,這就是讀寫分離的典型場景如下:
為了進一步的降低資料庫端的壓力(高并發的瓶頸),這個時候也會在業務層部署分布式緩存叢集(redis、memcached)等,把讀的壓力轉移給應用伺服器端,其實與資料主從的設計是遵循同一個原則,降低後端資料庫的壓力。
問題:
讀寫分離提高了資源的利用效率的同時也引出了一個問題,就是由于延時(網絡傳輸,操作)而引起的資料庫主從不一緻的問題,以下會詳細談相關的資料一緻性解決方案。
資料同步一緻性解決方案
1.半同步複制
辦法就是等主從同步完成之後,等主庫上的寫請求再傳回,這就是常說的“半同步複制"。
實作方案
mysql的半同步複制方案,下面我以mysql為例介紹。
MySQL半同步複制
MySQL的Replication預設是一個異步複制的過程,從MySQL5.5開始,MySQL以插件的形式支援半同步複制,我先談下異步複制,這樣可以更好的了解半同步複制。
1)異步複制
MySQL預設的複制是異步的,主庫在執行完用戶端送出的事務後會立即将結果返給給用戶端,并不關心從庫是否已經接收并處理,這樣就會有一個問題,主如果crash掉了,此時主上已經送出的事務可能并沒有傳到從庫上。
2)半同步複制
介于異步複制和全同步複制之間,主庫在執行完用戶端送出的事務後不是立刻傳回給用戶端,而是等待至少一個從庫接收到并寫到relay log中才傳回給用戶端。相對于異步複制,半同步複制提高了資料的安全性,同時它也造成了一定程度的延遲,這個延遲最少是一個TCP/IP往返的時間。是以,半同步複制最好在低延時的網絡中使用。
半同步複制原理:
- 事務在主庫寫完binlog後需要從庫傳回一個已接受,才放回給用戶端
- mysql5.5版本以後,以插件的形式存在,需要單獨安裝
- 確定事務送出後binlog至少傳輸到一個從庫
- 不保證從庫應用完成這個事務的binlog
- 性能有一定的降低
- 網絡異常或從庫當機,卡主庫,直到逾時或從庫恢複
該方案優點:
利用資料庫原生功能,比較簡單
該方案缺點:
主庫的寫請求時延會增長,吞吐量會降低
2.資料庫中間件
流程:
1)所有的讀寫都走資料庫中間件,通常情況下,寫請求路由到主庫,讀請求路由到從庫
2)記錄所有路由到寫庫的key,在主從同步時間視窗内(假設是500ms),如果有讀請求通路中間件,此時有可能從庫還是舊資料,就把這個key上的讀請求路由到主庫。
3)在主從同步時間過完後,對應key的讀請求繼續路由到從庫。
相關的中間件有:
1)canal:是阿裡巴巴旗下的一款開源項目,純Java開發,基于資料庫增量日志解析,提供增量資料訂閱&消費,目前主要支援了MySQL。
2)otter:也是阿裡開源的一個分布式資料庫同步系統,尤其是在跨機房資料庫同步方面,有很強大的功能。它是基于資料庫增量日志解析,實時将資料同步到本機房或跨機房的mysql/oracle資料庫。
兩者的差別在于:
otter目前嵌入式依賴canal,部署為同一個jvm,目前設計為不産生Relay Log。
otter目前允許自定義同步邏輯,解決各類需求。
該方案優點
能保證絕對一緻
該方案缺點:
資料庫中間件的成本較高
3.緩存記錄寫key法
寫流程:
1)如果key要發生寫操作,記錄在cache裡,并設定“經驗主從同步時間”的cache逾時時間,例如500ms
2)然後修改主資料庫
讀流程:
1)先到緩存裡檢視,對應key有沒有相關資料
2)有相關資料,說明緩存命中,這個key剛發生過寫操作,此時需要将請求路由到主庫讀最新的資料。
3)如果緩存沒有命中,說明這個key上近期沒有發生過寫操作,此時将請求路由到從庫,繼續讀寫分離。
該方案優點:
相對資料庫中間件,成本較低
該方案缺點:
為了保證“一緻性”,引入了一個cache元件,并且讀寫資料庫時都多了緩存操作。
以上就是資料庫主從同步一緻性方案詳解,如果有興趣了解更加深入的分布式大資料分布式檔案系統和分布式資料庫的一緻性,可以到我的部落格mikechen檢視:分布式資料庫資料一緻性的原理、與技術實作方案(文章)~
更多分布式架構系列、阿裡架構師進階系列,請檢視以下文章:
阿裡架構師進階從0到1全部合集(建議收藏)