前文《MySQL 數據庫事務與複製》分析了 MySQL 複製過程當中如何保證 binlog 和事務數據之間的一致性,本文進一步分析引入從庫後須要保證主從的數據一致性須要考慮哪些方面。html
MySQL 的原生複製架構原理如上圖所示。從庫的 I/O Thread 線程負責不斷讀取主庫的 binlog 日誌文件並寫入本地的 Relay log 臨時緩存。從庫的 SQL Thread 線程則不斷讀取 Relay log 重放事件入庫。整個過程看起來是比較簡單清晰的,但其中有幾個點對主從數據一致性有關鍵影響,咱們下面逐一分析。mysql
主從複製的場景下,產生數據不一致的現象有兩種:sql
從庫的 I/O Thread 是經過網絡讀取主庫的 binlog 的,若出現網絡故障,有可能產生數據丟失。爲避免網絡故障致使的數據丟失,網絡恢復後從庫從新鏈接上來須要知道從主庫 binlog 的哪一個位置從新傳輸數據。從庫須要記住中斷髮生時 binlog 的位置,並從該斷點處從新讀取,這個斷點咱們稱爲從庫的重傳檢查點。一個可靠的重傳檢查點必須是在從庫讀到數據並寫入到本地 Relay log 持久化以後纔可創建,不然都有丟失數據的可能。數據庫
因爲主從複製過程的分佈式特徵,須要保證複製過程的冪等性,也就是重複複製同一條數據最終不會產生重複的數據。防重策略是必須的,通常符合範式特徵的數據庫表設計經過主鍵來防重,而無主鍵表數據能夠經過全部字段聯合惟一索引來防重。有了防重策略就能夠任意回溯複製過程,而沒必要考慮從庫產生重複數據。緩存
爲了保證主從數據一致性,複製過程不只要保證不丟失、不重複,還須要保證操做順序一致。binlog 的事件日誌反應了主庫併發事務的操做序列,最終這種序列也要原樣反應到從庫上。因此原生複製架構爲了作到這點,採用了單線程模型的串行化操做。這也是沒辦法的,由於在數據庫層面是沒法知道不一樣數據之間的因果和依賴關係,所以沒法並行入庫。微信
原生的複製架構作到了無丟失、無重複和順序一致性,普通場景下基本可用,但也存在一些不足:網絡
一些特殊場景下的數據庫複製分佈,使用原生複製架構則不必定合適,可能的場景有:多線程
因此咱們才須要考慮針對特殊場景自定義複製架構,下面咱們看一個自定義複製架構的概念原理圖。架構
如上,自定義複製架構參考原生架構模擬成一個 MySQL 從庫,它內部包括三個主要角色:併發
因爲是自定義程序實現則能夠在無改造 MySQL 的前提下提供額外的功能,相對應用和 MySQL 均可以作到透明。相對原生複製架構的不足,自定義複製架構能夠提供更好的複製過程監控和管理能力,並支持異構數據轉換等等。而對於須要跨地域、跨機房且延時敏感的大型庫複製,則能夠經過適當的策略來加速複製過程。
好比前面提到的大型電商的訂單、交易類數據庫,通常都是分庫分表的。分庫分表後,不一樣庫表之間的數據其實在業務上是徹底獨立的,是能夠支持並行寫入的。因此咱們看上圖爲何畫了兩個 Load Worker,就是表達能夠針對業務獨立的表進行並行寫入。一條數據的複製延時包括:
總時長 T = P + N + L; 其中 P 是 Pull Worker 處理時長,N 是網絡傳輸時長, L 是 Load Worker 處理時長。
同一個庫的 binlog 是順序的很差並行拉取,傳輸過程的網絡時長也是剛性的,惟一能加速的就是入庫處理。按業務獨立的不一樣表能夠作到並行的多線程入庫操做,以縮短 L 的總體時長,以下圖所示。
本文分析了 MySQL 基於 binlog 的主從複製原理,從數據一致性的角度考慮分佈式網絡環境下主從架構設計的關鍵要素。在分析了 MySQL 原生複製架構的基礎上給出了一個靈活性和可控性更高的自定義複製架構的高層設計。理解了主從複製架構如何保證數據一致性後,咱們後面纔可進一步考慮在雙寫主庫的場景如何作雙向複製同步並保證雙主庫的數據最終一致性問題。這個系列下一篇文章會專門分析這個問題。
[1] MySQL Internals Manual. Replication.
[2] MySQL Internals Manual. The Binary Log.
[3] in355hz. 數據庫 ACID 的實現.
[4] jb51. MySQL 對 binlog 的處理說明.
[5] repls. 淺析 innodb_support_xa 與 innodb_flush_log_at_trx_commit.
[6] 68idc. MySQL 5.6 之 DBA 與開發者指南.
[7] csdn. 高性能 MySQL 主從架構的複製原理及配置詳解
下面是個人微信公衆號 「瞬息之間」,除了寫技術的文章、還有產品、行業和人生的思考,但願能和更多走在這條路上同行者交流。