MySQL主從復制(二)——原理、時延等問題解決

前言

在上一篇MySQL主從復制(一)——實戰文章中,我們簡單的提了一下它的實現原理,隨后即開始了其相關的實現實戰內容。在本篇文章中,我們主要詳細了解數據庫主從復制的實現原理以及其在同步過程中存在的時延問題。

1. 主從復制的形式

  • 一主一從
  • 主主復制
  • 一主多從:擴展系統讀取的性能,因為讀是在從庫讀取的;
  • 多主一從:MySQL5.7開始支持;
  • 聯級復制

2. 主從復制實現原理

主從復制原理圖

簡單來講,其過程為

  • 主庫的任何數據更改都會被記錄到二進制日志(binlog)中;
  • 從庫生成兩個線程,一個I/O線程,一個SQL線程
  • I/O線程去請求主庫 的binlog,并將得到的binlog日志寫到relay log(中繼日志) 文件中;
  • 主庫會生成一個 log dump 線程,用來給從庫 I/O線程傳binlog;
  • SQL 線程,會讀取relay log文件中的日志,從Exec_Master_Log_Pos位置開始執行讀取到的更新事件,將更新內容寫入到slave的db,來實現主從的操作一致,而最終數據一致;

我們可以發現從庫同步主庫數據的過程是串行化的,也就是說主庫上并行的操作,在從庫上會串行執行,由于從庫從主庫拷貝日志以及串行執行 SQL 的特點,在高并發場景下,從庫的數據一定會比主庫慢一些,是有延時的。所以經常出現,剛寫入主庫的數據可能是讀不到的,要過幾十毫秒,甚至幾百毫秒才能讀取到。這就是我們接下來要談到的主從同步時延問題

3.主從同步時延問題的產生

時延問題可能會導致我們新增的數據無法讀取到,我們針對業務的不同情況來決定我們是否允許有時延,若不允許,則需要我們進行相應的配置去解決。

3.1 時延情況觀察

我們在配置好的從庫上執行show slave status\G;可以看到如下參數:

  • Master_Log_File: SLAVE中的I/O線程當前正在讀取的主服務器二進制日志文件的名稱;
  • Read_Master_Log_Pos: 在當前的主服務器二進制日志中,SLAVE中的I/O線程已經讀取的位置;
  • Relay_Log_File: SQL線程當前正在讀取和執行的中繼日志文件的名稱;
  • Relay_Log_Pos: 在當前的中繼日志中,SQL線程已讀取和執行的位置;
  • Relay_Master_Log_File: 由SQL線程執行的包含多數近期事件的主服務器二進制日志文件的名稱;
  • Slave_IO_Running: I/O線程是否被啟動并成功地連接到主服務器上;
  • Slave_SQL_Running: SQL線程是否被啟動;
  • Seconds_Behind_Master: 從屬服務器SQL線程和從屬服務器I/O線程之間的時間差距,單位以秒計。

從以上的參數中,我們可以觀察得知主從數據庫的時延情況:

  • 從庫同步延遲情況出現的Seconds_Behind_Master不為0,這個數值可能會很大;
  • Relay_Master_Log_FileMaster_Log_File顯示bin-log的編號相差很大,說明bin-log在從庫上沒有及時同步,所以近期執行的bin-log和當前IO線程所讀的bin-log相差很大;
  • MySQL的從庫數據目錄下存在大量mysql-relay-log日志,該日志同步完成之后就會被系統自動刪除,存在大量日志,說明主從同步延遲很高。
3.2 主從同步延時問題的產生

1)MySQL數據庫主從同步延遲原理:主庫針對寫操作,順序寫binlog,從庫單線程去主庫順序讀”寫操作的binlog”,從庫取到binlog在本地原樣執行(隨機寫),來保證主從數據邏輯上一致。mysql的主從復制都是單線程的操作,主庫對所有DDL和DML產生binlog,binlog是順序寫,所以效率很高,slave的Slave_IO_Running線程到主庫取日志,效率比較高,下一步,問題來了,slave的Slave_SQL_Running線程將主庫的DDL和DML操作在slave實施。DML和DDL的IO操作是隨即的,不是順序的,成本高很多,還可能可slave上的其他查詢產生lock爭用,由于Slave_SQL_Running也是單線程的,所以一個DDL卡主了,需要執行10分鐘,那么所有之后的DDL會等待這個DDL執行完才會繼續執行,這就導致了延時。有朋友會問:“主庫上那個相同的DDL也需要執行10分,為什么slave會延時?”,答案是master可以并發,Slave_SQL_Running線程卻不可以。

2)MySQL數據庫主從同步延遲是怎么產生的?當主庫的TPS并發較高時,產生的DDL數量超過slave一個sql線程所能承受的范圍,那么延時就產生了,當然還有就是可能與slave的大型query語句產生了鎖等待。首要原因:數據庫在業務上讀寫壓力太大,CPU計算負荷大,網卡負荷大,硬盤隨機IO太高次要原因:讀寫binlog帶來的性能影響,網絡傳輸延遲。

4. 主從同步時延問題解決

在講解時延問題解決時,我們先大概了解MySql主從復制存在的問題:

  • 主庫宕機后,數據可能丟失
  • 從庫只有一個sql thread,在主庫寫壓力大的時候,復制可能存在時延
4.1 MySql提供的幾種主從復制機制:

(1)異步復制:MYSQL 默認的復制方式,就是主庫寫入binlog日志后即可成功返回客戶端,無須等待binlog日志傳遞給從庫的過程。但這樣一旦主庫發生宕機,就有可能出現數據丟失的情況。
(2)半同步復制(mysql semi-sync),解決數據丟失的問題,其原理如下:

  • 事務在主庫寫完binlog后需要從庫返回一個已接受,才返回給客戶端。簡單的講就是,主庫寫入 binlog 日志之后,就會將強制此時立即將數據同步到從庫,從庫將日志寫入自己本地的 relay log 之后,接著會返回一個 ack 給主庫,主庫接收到至少一個從庫的 ack 之后才會認為寫操作完成了
  • 5.5集成到mysql,以插件的形式存在,需要單獨安裝;
  • 確保事務提交后binlog至少傳輸到一個從庫 ;
  • 不保證從庫應用完這個事務的binlog;
  • 性能有一定的降低,響應時間會更長;
  • 網絡異常或從庫宕機,卡主主庫,直到超時或從庫恢復;

(3)并行復制,解決從庫復制延遲的問題,指的是從庫開啟多個線程,并行讀取 relay log 中不同庫的日志,然后并行重放不同庫的日志,這是庫級別的并行。其特點如下:

  • 5.6中新增;
  • 并行是指從庫多線程apply binlog ;
  • 庫級別并行應用binlog,同一個庫數據更改還是串行的(5.7版并行復制基于事務組)設置set global slave_parallel_workers=10;設置sql線程數為10;
4.2 時延問題解決
  • 分庫,將一個主庫拆分為多個主庫,每個主庫的寫并發就減少了幾倍,此時主從延遲可以忽略不計。

  • 打開 MySQL 支持的并行復制,多個庫并行復制。如果說某個庫的寫入并發就是特別高,單庫寫并發達到了 2000/s,并行復制還是沒意義。
    針對主從延遲,本人的經驗如下:

  • 業務量不大的:主庫能處理業務就全放在主庫吧,從庫只做災備,備份,對實時性要求不高的統計報表類工作;

  • 已經出現延遲的:一般來說,就慢慢等吧,試圖通過重啟db之類的操作是無法解決的,還會因為大事務回滾再重做導致花的時間更長;

  • 延遲N天無法解決的:那就重做slave。為什么會延遲N天,難道僅僅是因為從庫單線程嗎?我感覺大部分都是主庫上采用mixed的binlog_format,由于某種限制,無法基于statement,只好row模式復制。那么如果當前sql是全表掃描,傳到slave上執行時就是茫茫多次的全表掃描了。一般來說在slave上show proceslist看查看當前的system user正在執行什么,那就是問題SQL。如果pos點一直不動,也可以去主庫對應的binlog上查看下執行的是什么東西;

  • 出現延遲時,查看下當前slave的cpu和磁盤狀況:一般來說如果從庫沒有其他業務,單線程的原因,cpu跑滿一個核已經是極限了。磁盤io滿的話,確認下是否有其他進程或mysql線程影響了它(比如從庫正在dump或者超大的sql在執行),也可以嘗試調整下slave上關于io的幾個參數;

  • 從庫raid卡,務必設置成write back的寫策略

  • 批量的dml操作:批量的dml操作如果不做處理,一般必然會出現延遲,建議業務低峰期執行,并將批量操作做下調整,一次dml 10000行,sleep一會,再dml 10000行。具體的行數和sleep需要自己根據業務確定,能保證從庫不延遲就好;

  • 如果還是經常性的短時間延遲,那就嘗試加大從庫的硬件配置,比如上sata SSD,pcie等

  • 延遲的監控到位,可通過pt-heart-beat來準確監控延遲值,及時發現查看。

  • 5.5以后版本的,可以考慮采用半同步復制,能解決少量延遲引起的問題,不過對tps性能損耗較大

  • 升級到mysql 5.7吧,多線程復制并行復制,幾乎完美解決單線程復制引起的從庫延遲。

5. 總結

總的來說,我們可以根據業務場景的不同,合理的選擇是否主從復制后再結合讀寫分離,因為讀寫分離,是必須要面對時延這一問題,我們可以根據我們需求來確定到底是不是真的需要讀寫分離,因為我們也同樣可以利用redis緩存,或者其它緩存來緩解我們數據庫的壓力,而將從庫僅作為我們的備份,這樣我們就不需要去保證從庫無時延(即數據與主庫實時同步),所以具體的應用需要符合我們自己的業務場景。

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,119評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,382評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,038評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,853評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,616評論 6 408
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,112評論 1 323
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,192評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,355評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,869評論 1 334
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,727評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,928評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,467評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,165評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,570評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,813評論 1 282
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,585評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,892評論 2 372

推薦閱讀更多精彩內容