揭祕MySQL的主從同步實現方案

{"type":"doc","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"關於MySQL主從複製主要同步的是binlog日誌,涉及到三個線程,一個運行在主節點(log dump thread),其餘兩個(I/O thread, SQL thread)運行在從節點,如下圖所示:","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/7b/7b3620b6f6914d8c3f6c22a08f6d1ff4.webp","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"1、如何實現主從一致","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"(1)主節點 binary log dump 線程","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"當從節點連接主節點時,主節點會創建一個log dump 線程,用於發送binlog的內容。在讀取binlog中的操作時,此線程會對主節點上的binlog加鎖,當讀取完成,在發送給從節點之前,鎖會被釋放。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"(2)從節點I/O線程","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"當從節點上執行","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"start slave","attrs":{}}],"attrs":{}},{"type":"text","text":"命令之後,從節點會創建一個I/O線程用來連接主節點,請求主庫中更新的binlog。I/O線程接收到主節點binlog dump 進程發來的更新之後,保存在本地relay-log(中繼日誌)中。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"(3)從節點SQL線程","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"SQL線程負責讀取relay log中的內容,解析成具體的操作並執行,最終保證主從數據的一致性。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"2、一主多從同步?","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"對於每一個主從連接,都需要三個進程來完成。當主節點有多個從節點時,主節點會爲每一個當前連接的從節點建一個binlog dump 進程,而每個從節點都有自己的I/O進程,SQL進程。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"從節點用兩個線程將從主庫拉取更新和執行分成獨立的任務,這樣在執行同步數據任務的時候,不會降低讀操作的性能。比如,如果從節點沒有運行,此時I/O進程可以很快從主節點獲取更新,儘管SQL進程還沒有執行。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果在SQL進程執行之前從節點服務停止,至少I/O進程已經從主節點拉取到了最新的變更並且保存在本地relay日誌中,當服務再次起來之後,就可以完成數據的同步。","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/77/77a2626bd2c05ba5602a445d9adb7de6.webp","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"3、主從複製的基本過程","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"(1)從節點上的I/O 進程連接主節點,並請求從指定日誌文件的指定位置(或者從最開始的日誌)之後的日誌內容;","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"(2)主節點接收到來自從節點的I/O請求後,通過負責複製的I/O進程根據請求信息讀取指定日誌指定位置之後的日誌信息,返回給從節點。返回信息中除了日誌所包含的信息之外,還包括本次返回的信息的binlog file 的以及binlog position;","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"(3)從節點的I/O進程接收到內容後,將接收到的日誌內容更新到本機的relay log中,並將讀取到的binlog文件名和位置保存到master-info 文件中,以便在下一次讀取的時候能夠清楚的告訴Master“我需要從某個binlog 的哪個位置開始往後的日誌內容,請發給我”;","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"(4)Slave 的 SQL線程檢測到relay-log 中新增加了內容後,會將relay-log的內容解析成在主節點上實際執行過的操作,並在本數據庫中執行。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"4、MySQL 主從複製模式","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"MySQL 主從複製默認是異步的模式。MySQL增刪改操作會全部記錄在binlog中,當slave節點連接master時,會主動從master處獲取最新的bin log文件。並把bin log中的sql relay。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"(1)異步模式(mysql async-mode)","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"原理:客戶端提交 COMMIT 之後主庫,不需要等從庫返回任何結果,而是直接將結果返回給客戶端,這樣做的好處是不會影響主庫寫的效率,但可能會存在主庫宕機(就涼了),而 Binlog 還沒有同步到從庫的情況,也就是此時的主庫和從庫數據不一致。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"​","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這時候從從庫中選擇一個作爲新主,那麼新主則可能缺少原來主服務器中已提交的事務。所以,這種複製模式下的數據一致性是最弱的。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/8f/8fd64e7ca82812a1fabdb6203ba5d19c.webp","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"(2)半同步模式(mysql semi-sync)","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"原理:在客戶端提交 COMMIT 之後不直接將結果返回給客戶端,而是等待至少有一個從庫接收到了 Binlog,並且寫入到中繼日誌中,再返回給客戶端。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這樣做的好處就是提高了數據的一致性,當然相比於異步複製來說,至少多增加了一個網絡連接的延遲,降低了主庫寫的效率。MySql5.7支持設置應答從庫的個數,保證N個從庫同步完成後進行返回。","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/d7/d7da09de5cbcf91fbbe25902425b4aad.webp","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"半同步模式不是mysql內置的,從mysql 5.5開始集成,需要master 和slave 安裝插件開啓半同步模式。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"(3)全同步模式","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"全同步模式是指主節點和從節點全部執行了commit並確認纔會向客戶端返回成功。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"horizontalrule","attrs":{}},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"作者:架構精進之路,十年研發風雨路,大廠架構師,CSDN 博客專家,專注架構技術沉澱學習及分享,職業與認知升級,堅持分享接地氣兒的乾貨文章,期待與你一起成長","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"關注並私信我回復“01”,送你一份程序員成長進階大禮包,歡迎勾搭。","attrs":{}}]}],"attrs":{}},{"type":"horizontalrule","attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Thanks for reading!","attrs":{}}]}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章