Mysql官方檔案:Chapter 16 Replication
一、MySQL主從復制(異步復制,默認)
Mysql主從復制原理
Mysql的復制原理大致如下:
1.主庫記錄binlog日志
在每次準備提交事務完成資料更新前,主庫將資料更新的事件記錄到二進制日志binlog中,主庫上的sync_binlog引數控制binlog日志重繪到磁盤,
2.從庫IO執行緒將主庫的binlog日志復制到其本地的中繼日志relay log中
從庫會啟動一個IO執行緒,IO執行緒會跟主庫建立連接,然后主庫會啟動一個特殊的二進制轉儲執行緒(binlog dump),二進制轉儲執行緒會讀取主庫上binlog中的事件,它不會一直對事件進行輪詢,當它追趕上了主庫就會進入睡眠狀態,直到主庫發送信號量通知其有新事件產生才會被喚醒,
3.從庫的SQL執行緒進行重放
從庫的SQL執行緒從中繼日志relay log中讀取事件并在從庫執行,從而實作從庫資料的更新,

需要注意的是:主庫上并發的修改操作在從庫上只能串行化執行,因為只有一個SQL執行緒來重放中繼日志,這也是很多作業負載的性能瓶頸所在,雖然有一些針對你該問題的解決方案,但大多數用戶仍然受制于單執行緒,在老版本的mysql中,IO執行緒是單執行緒的,但新版本IO執行緒也可以是多執行緒的,但無論怎樣,SQL執行緒是單執行緒的,
二、半同步復制(Semisynchronous Replication)
1.主從延遲導致資料丟失
Mysql5.5之前的復制是異步的,主庫和從庫的資料有一定的延遲,這樣就存在一個問題:當主庫上寫入一個事務并提交成功,而從庫尚未收到主庫推送的binlog日志,如果此時主庫宕機造成主庫上的事務binlog丟失,此時從庫就可能損失這個事務,從而造成主從不一致,為了解決這個問題,Mysql5.5引入了半同步復制機制,
2.半同步復制
官方檔案:17.3.8 Semisynchronous Replication
半同步復制是從Mysql5.5版本開始,以插件的形式支持的,默認情況下是關閉的,使用時需在配置中打開,
Mysql默認的復制是異步的,主庫在將事件寫入binlog后即成功回傳客戶端,但并不知道從庫是否以及何時會獲取和處理日志,而至于半同步復制,主庫在提交后執行事務提交的執行緒將一直等待,直到至少有一個半同步從庫確認已接收到所有事件,從庫僅在將事件寫入其中繼日志(relay log)并重繪到磁盤后,才對接收到事務的事件進行確認,此時,主庫收到確認后才會對客戶端進行回應,半同步復制保證了事務成功提交后,至少有兩份日志記錄,一份在主庫的binlog上,另一份在至少一個從庫的中繼日志relay log上,這樣就進一步保證了資料的完整性,

圖中步驟①②③中任何一個步驟中主庫宕機,則事務并未提交成功,從庫也沒有收到事務對應的binlog日志,所以主從資料是一致的,
需要注意的是:
(1)主庫和從庫都要啟用半同步復制才會進行半同步復制功能,否則主庫會還原為默認的異步復制,
(2)當主庫等待超時時,也會還原為默認的異步復制,當至少有一個從庫趕上時,主庫會恢復到半同步復制,
三、并行復制(多執行緒復制,multi-threaded slave)
1.主從延遲問題
由于主庫上可以多客戶端并發的寫入,當主庫的TPS較高時,由于從庫的SQL執行緒是單執行緒的,導致從庫處理速度可能會跟不上主庫的處理速度,從而造成了延遲,
主庫并發達到1000/s時,從庫的延時會有幾毫秒,幾乎可以忽略, 主庫并發達到2000/s時,從庫的延時會有幾十毫秒, 主庫并發達到4000/s,6000/s,8000/s時,此時主庫的壓力很大,都快掛了,從庫的延時會達到幾秒, 上面的只是經驗值,但是是在合理的范圍內,(來源于中華石杉)
可以通過監控 show slave status 命令輸出的Seconds_Behind_Master引數的值來檢測主從延時:
- NULL:表示io_thread或是sql_thread有任何一個發生故障;
- 0:該值為零,表示主從復制良好;
- 正值:表示主從已經出現延時,數字越大表示從庫延遲越嚴重,
相關博客:【MySQL】請不要用SECONDS_BEHIND_MASTER來衡量MySQL主備的延遲時間
2.并行復制
所謂并行復制,指的是從庫開啟多個SQL執行緒,并行讀取relay log中不同庫的日志,然后并行重放不同庫的日志,這是庫級別的并行,
Mysql5.6中的并行復制
MySQL 5.5版本不支持并行復制,MySQL 5.6版本開始支持并行復制,但是其并行只是基于schema的,也就是基于庫的,當有多個庫時多個庫可以并行進行復制,而庫與庫之間互不干擾,但多數情況下,可能只有單schema,即只有單個庫,那基于schema的復制就沒什么用了,
其核心思想是:不同schema下的表并發提交時的資料不會相互影響,即slave節點可以用對relay log中不同的schema各分配一個類似SQL功能的執行緒,來重放relay log中主庫已經提交的事務,保持資料與主庫一致,
只需設定引數slave_parallel_workers即可開啟并行復制,例如設定 slave_parallel_workers= 4,即有4個SQL Thread(coordinator執行緒)來進行并行復制,
Mysql5.7中的并行復制
而MySQL 5.7版本對并行復制進一步改進,已經支持“真正”的并行復制功能,是基于組提交的并行復制,官方稱為enhanced multi-threaded slave(簡稱MTS),復制延遲問題已經得到了極大的改進,
其核心思想:一個組提交的事務都是可以并行回放(配合binary log group commit);slave機器的relay log中 last_committed相同的事務(sequence_num不同)可以并發執行,
通過設定引數slave_parallel_workers>0并且global.slave_parallel_type=‘LOGICAL_CLOCK’,即可支持一個schema下,slave_parallel_workers個的worker執行緒并發執行relay log中主庫提交的事務,
更多內容可以參考丁奇的這篇文章:各版本MySQL并行復制的實作及優缺點
3. ★踩坑案例(主從延遲問題解決方法)
中華石杉的視頻中也提到他們在生產中遇到了這個問題,和這篇文章中出現的問題類似:【踩坑記錄】記一次MySQL主從復制延遲的坑,大致原因就是更新后立即進行讀操作,由于主從復制延遲問題,可能讀到空的內容,而解決方法呢,中華石杉也說了,并行復制這些在一定程度上會起點作用,但并不是根本解決方案,下面是視頻中的筆記:
其實這塊東西我們經常會碰到,就比如說用了mysql主從架構之后,可能會發現,剛寫入庫的資料結果沒查到,結果就完蛋了,,,, 所以實際上你要【考慮好應該在什么場景下來用這個mysql主從同步,建議是一般在讀遠遠多于寫,而且讀的時候一般對資料時效性要求沒那么高的時候,才用mysql主從同步】 所以這個時候,我們可以考慮的一個事情就是,【你可以用mysql的并行復制,但問題是那是庫級別的并行,所以有時候作用不是很大】 所以通常來說,對于那種寫了之后立馬就要保證可以查到的場景,【采用強制讀主庫的方式】,這樣就可以保證你肯定的可以讀到資料,【其實用一些資料庫中間件是沒問題的,】 一般來說,如果主從延遲較為嚴重: 1、架構層面:分庫,將一個主庫拆分為多個,比如將1個庫拆為4個主庫,每個主庫的寫并發就500/s,此時主從延遲可以忽略不計, 2、開啟mysql支持的并行復制,多個庫并行復制,但如果說某個庫的寫入并發就是特別高,單庫寫并發達到了2000/s,并行復制還是沒意義,28法則,很多時候比如說,就是少數的幾個訂單表,寫入了2000/s,其他幾十個表10/s, 3、代碼層面:重寫代碼,寫代碼的同學,要慎重,當時我們其實短期是讓那個同學重寫了一下代碼,插入資料之后直接就更新,不要查詢, 4、直連主庫,如果確實存在插入后立馬要求就查詢到,然后根據結果(比如某個狀態)反過來執行一些操作,則可以對這個查詢設定【直連主庫】,但不推薦這種方法,這么搞導致讀寫分離的意義就喪失了,
四、多源復制(Multi-Source Replication)
官方檔案:16.1.4 MySQL Multi-Source Replication
MySQL從5.7版本開始支持多源復制的,MySQL 5.7之前只能實作一主一從、一主多從或者多主多從的復制,如果想實作多主一從的復制,只能使用 MariaDB,但是 MariaDB 又與官方的 MySQL 版本不兼容,MySQL 5.7 開始支持了多主一從的復制方式,也就是多源復制,所以,多源復制至少需要兩個Master和一個Slave,

1.多源復制使用場景
- 資料分析部門會需要各個業務部門的部分資料做資料分析,這個時候就可以用到多源復制把各個主資料庫的資料復制到統一的資料庫中,
- 在從服務器進行資料匯總,如果我們的主服務器進行了分庫分表的操作,為了實作后期的一些資料統計功能,往往需要把資料匯總在一起再統計,
- 在從服務器對所有主服務器的資料進行備份,在MySQL 5.7之前每一個主服務器都需要一個從服務器,這樣很容易造成資源浪費,同時也加大了DBA的維護成本,但MySQL 5.7引入多源復制,可以把多個主服務器的資料同步到一個從服務器進行備份,
2.配置多源復制
配置多源復制時,可以將主庫配置為使用基于GTID的復制或基于binlog位置的復制,
官方檔案:
Section 16.1.3.4, “Setting Up Replication Using GTIDs”
Section 16.1.2.1, “Setting the Replication Master Configuration”
MySQL 5.7多源復制實踐
總結:
mysql默認的復制是異步的,主庫寫入了binlog后就會回傳給客戶端,而無論從庫是否復制成功,由于主從延遲,當主庫掛掉時會造成資料丟失,為了解決資料丟失問題,引入了半同步復制機制,同時為了解決復制的性能問題,可以開啟多執行緒并行復制,(mysql5.5不支持并行復制,mysql5.6開始支持基于schema的并行復制,mysql5.7則對5.6并行復制進行改進增強)
mysql的一主一/多從、雙主都是一個復制源,而mysql5.7多源復制則允許多個mssql同時對一個從庫進行復制,
面試題:
1.為什么要讀寫分離?如何實作mysql的讀寫分離?
2.mysql主從復制的原理?
3.主從同步延時如何解決?主從同步資料丟失問題如何解決?
MySQL實際上在這一塊有兩個機制:
半同步復制,用來解決因主從延時造成資料丟失問題;并行復制,用來解決主從同步延時性能問題,
4.什么是多源復制?
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/92732.html
標籤:MySQL
上一篇:Mysql優化思路
下一篇:聊一聊分庫分表及它生產的一些概念
