深度探索MySQL主從複製原理


基本概念

<font color = >
將master數據庫中的DDL和DML操作通過 二進制日誌(BINLOG) 傳輸到slave數據庫上,然後將這些日誌重新執行(重做);從而使得slave數據庫的數據與master數據庫保持一致。

MySQL數據庫自身提供的主從複製功能可以方便的實現數據的多處自動備份,實現數據庫的拓展。多個數據備份不僅可以加強數據的安全性,通過實現讀寫分離還能進一步提升數據庫的負載性能。

MySQL 主從複製是指數據可以從一個MySQL數據庫服務器主節點複製到一個或多個從節點。MySQL 默認採用異步複製方式,這樣從節點不用一直訪問主服務器來更新自己的數據,數據的更新可以在遠程連接上進行,從節點可以複製主數據庫中的所有數據庫或者特定的數據庫,或者特定的表。


MySQL 主從複製的主要用途

1、讀寫分離

在開發工作中,有時候會遇見某個 sql 語句需要鎖表,導致暫時不能使用讀的服務,這樣就會影響現有業務,使用主從複製,讓主庫負責寫,從庫負責讀,這樣,即使主庫出現了鎖表的情景,通過讀從庫也可以保證業務的正常運作

2、數據實時備份,當系統中某個節點發生故障時,可以方便的故障切換

3、高可用性(HA)

儘量縮短因日常維護操作(計劃)和突發的系統崩潰(非計劃)所導致的停機時間,以提高系統和應用的可用性

4、架構擴展

隨着系統中業務訪問量的增大,如果是單機部署數據庫,就會導致I/O訪問頻率過高。有了主從複製,增加多個數據存儲節點,將負載分佈在多個從節點上,降低單機磁盤I/O訪問的頻率,提高單個機器的I/O性能


MySQL 主從形式

MySQL 主從複製比較靈活,形式多種

  • 一主一從
  • 主主複製(互爲主從)
  • 一主多從(常用於擴展系統讀取性能,因爲讀是在從庫讀取的)
  • 多主一從(5.7開始支持)
  • 聯級複製

一主一從和一主多從是最常見的主從架構,實施起來簡單並且有效,不僅可以實現HA,而且還能讀寫分離,進而提升集羣的併發能力,一主多從常用於擴展系統讀取性能,因爲讀是在從庫讀取的

多主一從可以將多個mysql數據庫備份到一臺存儲性能比較好的服務器上

雙主複製,也就是互做主從複製每個master既是master,又是另外一臺服務器的slave。這樣任何一方所做的變更,都會通過複製應用到另外一方的數據庫中。

級聯複製就是master服務器,只給一臺slave服務器同步數據,然後slave服務器在向後端的所有slave服務器同步數據,降低master服務器的寫壓力,和複製數據的網絡IO。

級聯複製模式下,部分slave的數據同步不連接主節點,而是連接從節點。因爲如果主節點有太多的從節點,就會損耗一部分性能用於replication,那麼我們可以讓3~5個從節點連接主節點,其它從節點作爲二級或者三級與從節點連接,這樣不僅可以緩解主節點的壓力,並且對數據一致性沒有負面影響


MySQL 主從複製原理剖析

MySQL主從複製涉及到三個線程,一個運行在主節點(log dump thread),其餘兩個(I/O thread, SQL thread)運行在從節點,如下圖所示:

  • Binary log:主數據庫的二進制日誌
  • Relay log:從服務器的中繼日誌

基本原理概述如下:

  • 從庫生成兩個線程一個I/O線程,一個SQL線程
  • I/O線程去請求主庫的binlog,並將得到的binlog日誌寫到relay log(中繼日誌) 文件中
  • 主庫會生成一個 log dump 線程,用來給從庫 i/o線程傳binlog
  • SQL 線程,會讀取relay log文件中的日誌,並解析成具體操作,來實現主從的操作一致,而最終數據一致

詳細過程:

主節點 binary log dump 線程

當從節點連接主節點時,主節點會創建一個log dump 線程用於發送bin-log的內容在讀取bin-log中的操作時,此線程會對主節點上的bin-log加鎖,當讀取完成,甚至在發動給從節點之前,鎖會被釋放。

從節點I/O線程

當從節點上執行 start slave 命令之後,從節點會創建一個I/O線程用來連接主節點,請求主庫中更新的bin-log

I/O線程接收到主節點binlog dump 進程發來的更新之後,保存在本地relay-log中。

從節點SQL線程

SQL線程負責讀取relay log中的內容,解析成具體的操作並執行,最終保證主從數據的一致性

對於每一個主從連接,都需要三個進程來完成。當主節點有多個從節點時,主節點會爲每一個當前連接的從節點建一個binary log dump 進程,而每個從節點都有自己的I/O進程,SQL進程。從節點用兩個線程將從主庫拉取更新和執行分成獨立的任務,這樣在執行同步數據任務的時候,不會降低讀操作的性能

比如,如果從節點沒有運行,此時I/O進程可以很快從主節點獲取更新,儘管SQL進程還沒有執行。如果在SQL進程執行之前從節點服務停止,至少I/O進程已經從主節點拉取到了最新的變更並且保存在本地relay日誌中,當服務再次起來之後,就可以完成數據的同步。


要實施複製,首先必須打開Master 端的binary log(bin-log)功能,否則無法實現。

因爲整個複製過程實際上就是Slave 從Master 端獲取該日誌然後再在自己身上完全順序的執行日誌中所記錄的各種操作。如下圖所示:

主從複製原理運行流程:

  • 從節點上的I/O 進程連接主節點,並請求從指定日誌文件的指定位置(或者從最開始的日誌)之後的日誌內容
  • 主節點接收到來自從節點的I/O請求後,通過負責複製的I/O進程根據請求信息讀取指定日誌指定位置之後的日誌信息,返回給從節點。返回信息中除了日誌所包含的信息之外,還包括本次返回的信息的bin-log file 的以及bin-log position;
  • 從節點的I/O進程接收到內容後,將接收到的日誌內容更新到本機的relay log中,並將讀取到的binary log文件名和位置保存到master-info 文件中,以便在下一次讀取的時候能夠清楚的告訴Master“我需要從某個bin-log 的哪個位置開始往後的日誌內容,請發給我”;
  • Slave 的 SQL線程檢測到relay-log 中新增加了內容後,會將relay-log的內容解析成在主節點上實際執行過的操作,並在本數據庫中執行

MySQL 主從複製模式

MySQL主從複製有異步模式、半同步模式、GTID模式以及多源複製模式。

MySQL 主從複製默認是異步的模式。MySQL增刪改操作會全部記錄在binary log中,當slave節點連接master時,會主動從master處獲取最新的bin log文件。並把bin log中的sql relay。


異步模式(mysql async-mode)

MySQL默認的複製即是異步的,主庫在執行完客戶端提交的事務後會立即將結果返給給客戶端,並不關心從庫是否已經接收並處理,這樣就會有一個問題,主如果crash掉了,此時主上已經提交的事務可能並沒有傳到從庫上,如果此時,強行將從提升爲主,可能導致新主上的數據不完整。

主庫將事務 Binlog 事件寫入到 Binlog 文件中,此時主庫只會通知一下 Dump 線程發送這些新的 Binlog,然後主庫就會繼續處理提交操作,而此時不會保證這些 Binlog 傳到任何一個從庫節點上。


半同步模式(Semisynchronous replication)

半同步模式下主節點只需要接收到其中一臺從節點的返回信息,就會commit;否則需要等待直到超時時間然後切換成異步模式再提交。主庫不需要等待所有從庫給主庫反饋。同時,這裏只是一個收到的反饋,而不是已經完全完成並且提交的反饋,如此,節省了很多時間

這樣做的目的可以使主從數據庫的數據延遲縮小(相比較全同步),可以提高數據安全性,確保了事務提交後,binlog至少傳輸到了一個從節點上,不能保證從節點將此事務更新到db中。性能上會有一定的降低,響應時間會變長。同時它也造成了一定程度的延遲,這個延遲最少是一個TCP/IP往返的時間。所以,半同步複製最好在低延時的網絡中使用。如下圖所示:


全同步模式(Fully synchronous replication)

全同步模式是指主節點和從節點全部執行了commit並確認纔會向客戶端返回成功。指當主庫執行完一個事務,所有的從庫都執行了該事務才返回給客戶端。因爲需要等待所有從庫執行完該事務才能返回,所以全同步複製的性能必然會收到嚴重的影響。

當主庫提交事務之後,所有的從庫節點必須收到、APPLY並且提交這些事務,然後主庫線程才能繼續做後續操作。但缺點是,主庫完成一個事務的時間會被拉長,性能降低。

我們先來介紹一下binlog記錄格式:


binlog記錄格式

MySQL 主從複製有三種方式:

  • 基於SQL語句的複製(statement-based replication,SBR)
  • 基於行的複製(row-based replication,RBR)
  • 混合模式複製(mixed-based replication,MBR)。

對應的binlog文件的格式也有三種STATEMENT,ROW,MIXED

  • SBR 是記錄 SQL 語句在binlog中,Mysql 5.1.4 及之前的版本都是使用的這種複製格式。優點是只需要記錄會修改數據的SQL 語句到binlog中,減少了binlog日質量,節約I/O,提高性能。缺點是在某些情況下,會導致主從節點中數據不一致(比如sleep(),now()等)。

  • RBR 是 mysql master 將SQL語句分解爲基於Row更改的語句並記錄在bin log中,也就是隻記錄哪條數據被修改了,修改成什麼樣。優點是不會出現某些特定情況下的存儲過程、或者函數、或者trigger的調用或者觸發無法被正確複製的問題。缺點是會產生大量的日誌,尤其是修改table的時候會讓日誌暴增,同時增加bin log同步時間。也不能通過bin log解析獲取執行過的sql語句,只能看到發生的data變更。

  • MBR:MySQL NDB cluster 7.3 和7.4 使用的MBR。是以上兩種模式的混合,對於一般的複製使用STATEMENT模式保存到binlog,對於STATEMENT模式無法複製的操作則使用ROW模式來保存,MySQL會根據執行的SQL語句選擇日誌保存方式


GTID複製模式

  • 在傳統的複製裏面,當發生故障,需要主從切換,需要找到binlog和pos點,然後將主節點指向新的主節點,相對來說比較麻煩,也容易出錯。在MySQL 5.6裏面,不用再找binlog和pos點,我們只需要知道主節點的ip,端口,以及賬號密碼就行,因爲複製是自動的,MySQL會通過內部機制GTID自動找點同步

  • 多線程複製(基於庫),在MySQL 5.6以前的版本,slave的複製是單線程的。一個事件一個事件的讀取應用。而master是併發寫入的,所以延時是避免不了的。唯一有效的方法是把多個庫放在多臺slave,這樣又有點浪費服務器。在MySQL 5.6裏面,我們可以把多個表放在多個庫,這樣就可以使用多線程複製


基於GTID複製實現的工作原理

  • 主節點更新數據時,會在事務前產生GTID,一起記錄到binlog日誌中。
  • 從節點的I/O線程將變更的bin log,寫入到本地的relay log中
  • SQL線程從relay log中獲取GTID,然後對比本地binlog是否有記錄(所以MySQL從節點必須要開啓binary log)。
  • 如果有記錄,說明該GTID的事務已經執行,從節點會忽略。
  • 如果沒有記錄,從節點就會從relay log中執行該GTID的事務,並記錄到bin log
  • 在解析過程中會判斷是否有主鍵,如果沒有就用二級索引,如果有就用全部掃描

總結

MySQL 主從複製是 MySQL高可用,高性能的基礎,有了這個基礎,MySQL的部署會變得簡單、靈活並且具有多樣性,從而可以根據不同的業務場景做出靈活的調整。


參考:邸小麗《主從複製原理》

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章