Mysql主從複製(一)原理介紹

官方文檔

Mysql主從複製(MySQL Replication)見官方文檔17章介紹:Chapter 17 Replication

Mysql主從複製概念

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

Mysql主從複製好處

  • 讀寫分離,使數據庫能支持更大的併發;在報表中尤其重要。由於部分報表sql語句非常的慢,導致鎖表,影響前臺服務。如果前臺使用master,報表使用slave,那麼報表sql將不會造成前臺鎖,保證了前臺速度。
  • 數據實時備份,當系統中某個節點發生故障時,可以方便的故障切換
  • 高可用HA,確保數據安全,做數據的熱備,作爲後備數據庫,主數據庫服務器故障後,可切換到從數據庫繼續工作,避免數據的丟失
  • 架構擴展,隨着系統中業務訪問量的增大,如果是單機部署數據庫,就會導致I/O訪問頻率過高。有了主從複製,增加多個數據存儲節點,將負載分佈在多個從節點上,降低單機磁盤I/O訪問的頻率,提高單個機器的I/O性能。
  • Mysql 主從複製是mysql 高可用,高性能的基礎,有了這個基礎,mysql 的部署會變得簡單、靈活並且具有多樣性,從而可以根據不同的業務場景做出靈活的調整。

Mysql主從複製原理

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

在這裏插入圖片描述
主節點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日誌中,當服務再次起來之後,就可以完成數據的同步。

複製的基本過程

  • 從節點上的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的內容解析成在主節點上實際執行過的操作,並在本數據庫中執行。

各種文件介紹,詳見17.2.4.2 Slave Status Logs
relay log:我們在上文中已經提到,slave IO線程從master讀取的binlog數據首先保存在本地的relay log中;此後SQL線程即可從relay log中讀取變更操作並在本地應用。嚴格意義上說,relay log的內容應該與master binlog逐字節一致的(byte-to-byte)。

master info:master-info log文件保存了slave與當前master建立鏈接的一些配置信息和鏈接狀態,日誌中包括:master的host名稱、login認證信息,以及slave讀取master binlog的位置信息。在5.6之前,信息保存在master.info文件中,5.6之後,可以通過“–master-info-repository=TABLE”啓動參數(或者配置文件)將信息保存在“mysql.slave_master_info”系統表中。

relay log info:用於記錄relay log執行點的狀態信息,在5.6之前默認寫入relay-log.info文件,5.6之後可以通過“–relay-log-info-repository=TABLE”將信息寫入“mysql.slave_relay_log_info”系統表中。爲了避免crash對數據帶來的不一致問題,強烈建議將master-info、relay-log-info採用事務性表,而且建議開啓“–relay-log-recovery”。不過很遺憾的是,在5.6.5之前的版本中,slave_master_info、slave_relay_log_info表默認爲MyISAM,需要手動修改爲InnoDB。

binlog:這個大家都很熟悉,slave上也可以開啓binlog功能,比如slave是其他slave的master時。relay log內容格式與binlog一樣,也可以使用mysqlbinlog shell查看。

MySQL主從複製模式

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

異步模式,無法保證當master失效後所有的updates已經複製到了slaves上,只有重啓master才能繼續恢復這些數據,如果master因爲宿主機器物理損壞而無法修復,那些尚未複製到slaves上的updates將永久性丟失;因此異步方式存在一定的數據丟失的風險,但它的優點就是master支持的write併發能力較強,因爲master上的writes操作與slaves的複製是互爲獨立的。

這種模式,slaves總有一定的延後,這種延後在事務操作密集的應用中更加明顯,不過通常這種延後時間都極其短暫的。從另一個方面來說,異步方式不要求slaves必須時刻與master建立鏈接,可能slaves離線、中斷了replication進程或者鏈接的傳輸延遲很高,這都不會影響master對writes請求的處理效率。
在這裏插入圖片描述
半同步模式(Semi-synchronous)
“半同步”並不是MySQL內置的replication模式,而且由插件實現,即在使用此特性之前,需要在master和slaves上安裝插件,且通過配置文件開啓“半同步”。當slave與master建立連接時會表明其是否開啓了“半同步”特性;此模式正常運作,需要master和至少一個slaves同時開啓,否則仍將採用“異步”複製。

與異步複製相比,半同步提高了數據一致性,降低了數據丟失的風險。但是它也引入了一個問題,就是master阻塞等待slaves的確認信息,在一定程度上降低了master的writes併發能力,特別是當slaves與master之間網絡延遲較大時;因此我們斷定,半同步slaves應該部署在與master臨近的網絡中,爲了提高數據一致性,我們有必要將半同步作爲replication的首選模式。

在實際的部署環境中,並不要求所有的slaves都開啓半同步,我們可以將與master臨近的slaves開啓半同步,將那些“遠距分佈”的slaves使用異步。

這種模式下在master上執行事務提交的線程,在事務提交後將會阻塞,直到至少一個“半同步”的slave返回確認消息(ACK)或者所有的半同步slave都等待超時;slave將接收到事務的信息寫入到本地的relay log文件且flush到磁盤後,纔會向master返回確認消息,需要注意slave並不需要此時就執行事務提交,此過程可以稍後進行。當所有的半同步slaves均在指定的時間內沒有返回確認消息,即timeout,那麼此後master將轉換成異步複製模式,直到至少一個半同步slave完全跟進纔會轉換爲半同步模式。在master阻塞結束後纔會返回給客戶端執行的狀態,此期間不會處理其他的事務提交,當write請求返回時即表明此操作在master上提交成功,且在至少一個半同步slaves也複製成功或者超時,阻塞超時並不會導致事務的rollback。如下圖所示:
在這裏插入圖片描述

  • 全同步模式
    主節點和從節點全部執行了commit並確認纔會向客戶端返回成功。

binlog記錄格式

MySQL 主從複製有三種方式:

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

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

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

GTID複製模式

GTID全名爲Global Transaction Identifiers,全局事務性ID。在傳統的複製裏面,當發生故障,需要主從切換,需要找到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主從形式

一主一從和一主多從是最常見的主從架構,實施起來簡單並且有效,不僅可以實現HA,而且還能讀寫分離,進而提升集羣的併發能力。

  • 一主一從
    在這裏插入圖片描述

  • 一主多從
    提高系統的讀性能
    在這裏插入圖片描述

  • 多主一從
    從5.7開始支持,多主一從可以將多個mysql數據庫備份到一臺存儲性能比較好的服務器上
    在這裏插入圖片描述

  • 雙主複製
    也就是互做主從複製,每個master既是master,又是另外一臺服務器的slave。這樣任何一方所做的變更,都會通過複製應用到另外一方的數據庫中,這種模式不建議採用,對於多點寫入的架構模式(write操作密集型),建議採用MySQL Cluster!這種方式總是會引入“鎖併發”、“數據不一致”等問題,僅供參考!(3M架構)
    在這裏插入圖片描述

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

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