盤點(diǎn)數(shù)據(jù)庫(kù)主從延遲的九個(gè)原因以及解決方案
前言
大家好,我是撿田螺的小男孩。
我們來(lái)看一道字節(jié)面試題:mysql主從延遲的原因有哪些?你遇到的最大延遲是多大?如何解決?
我以前見過(guò)的最大延遲是3個(gè)多小時(shí)。本文我們一起來(lái)聊聊主從延遲吧。
- 主從延遲的定義
- 主從延遲原因的9個(gè)原因以及解決方案
1. 主從延遲是怎么定義的呢?
與主從數(shù)據(jù)同步相關(guān)的時(shí)間點(diǎn)有三個(gè)
- 主庫(kù)執(zhí)行完一個(gè)事務(wù),寫入binlog,我們把這個(gè)時(shí)刻記為T1;
- 主庫(kù)同步數(shù)據(jù)給從庫(kù),從庫(kù)接收完這個(gè)binlog的時(shí)刻,記錄為T2;
- 從庫(kù)執(zhí)行完這個(gè)事務(wù),這個(gè)時(shí)刻記錄為T3。
所謂主從延遲,其實(shí)就是指同一個(gè)事務(wù),在從庫(kù)執(zhí)行完的時(shí)間和在主庫(kù)執(zhí)行完的時(shí)間差值,即T3-T1。
主從復(fù)制原理不記得的伙伴,可以看這個(gè)圖哈:
圖片
2. 主從延遲原因以及解決方法
2.1 網(wǎng)絡(luò)延遲,優(yōu)化網(wǎng)絡(luò)
網(wǎng)絡(luò)延遲是導(dǎo)致主從延遲的一個(gè)重要因素。我們要確保主從服務(wù)器之間的網(wǎng)絡(luò)連接是高速且穩(wěn)定的??梢钥紤]使用專用網(wǎng)絡(luò)連接或提高網(wǎng)絡(luò)帶寬。
比如帶寬20M升級(jí)到100M類似意思等。
2.2 從庫(kù)的壓力大,多搞幾個(gè)從庫(kù)分散壓力
如果從庫(kù)的壓力大,也會(huì)導(dǎo)致主從延遲。
比如主庫(kù)直接影響業(yè)務(wù)的,大家可能使用會(huì)比較克制,因此一般查詢都打到從庫(kù)了,結(jié)果導(dǎo)致從庫(kù)查詢消耗大量CPU,影響同步速度,最后導(dǎo)致主從延遲。
這種情況的話,可以搞了一主多從的架構(gòu),即多接幾個(gè)從庫(kù)分?jǐn)傋x的壓力,增加從庫(kù)的數(shù)量可以分散讀取負(fù)載,提高數(shù)據(jù)同步的速度和可靠性。 另外,還可以把binlog接入到Hadoop這類系統(tǒng),讓它們提供查詢的能力。
2.3 數(shù)據(jù)庫(kù)參數(shù)配置不合理,優(yōu)化調(diào)整
調(diào)整MySQL數(shù)據(jù)庫(kù)中的相關(guān)參數(shù),如binlog格式、binlog緩沖區(qū)大小、innodb_flush_log_at_trx_commit等,以優(yōu)化性能。
適當(dāng)?shù)膮?shù)設(shè)置可以減少磁盤I/O和事務(wù)提交延遲。
2.4 使用半同步復(fù)制
半同步復(fù)制是介于全同步復(fù)制和異步復(fù)制之間的一種復(fù)制方式。主庫(kù)在提交事務(wù)時(shí)需要等待至少一個(gè)從庫(kù)接收到并寫入到relay log中才返回結(jié)果給客戶端。
圖片
這可以提高數(shù)據(jù)的安全性,并減少主從延遲。但需要注意的是,半同步復(fù)制可能會(huì)增加寫操作的延遲
2.5 升級(jí)硬件配置
如果從庫(kù)所在的機(jī)器比主庫(kù)的機(jī)器性能差,會(huì)導(dǎo)致主從延遲,這種情況比較好解決,只需選擇主從庫(kù)一樣規(guī)格的機(jī)器就好。
因此,我們可以:
- 升級(jí)從服務(wù)器的硬件,特別是磁盤I/O系統(tǒng)和CPU,以便更快地應(yīng)用復(fù)制事件。
- 使用SSD可以顯著提高I/O性能。
這是減少主從延遲時(shí)間,最簡(jiǎn)單粗暴的方法~~
2.6 避免大事務(wù)
- 可以將大事務(wù)分解為多個(gè)小事務(wù)。
如果一個(gè)事務(wù)執(zhí)行就要10分鐘,那么主庫(kù)執(zhí)行完后,給到從庫(kù)執(zhí)行,最后這個(gè)事務(wù)可能就會(huì)導(dǎo)致從庫(kù)延遲10分鐘啦。日常開發(fā)中,我們?yōu)槭裁刺貏e強(qiáng)調(diào),不要一次性delete太多SQL,需要分批進(jìn)行,其實(shí)也是為了避免大事務(wù)。另外,大表的DDL語(yǔ)句,也會(huì)導(dǎo)致大事務(wù),大家日常開發(fā)關(guān)注一下哈。
2.7 使用并行復(fù)制
- 在MySQL 5.6及以上版本中,可以使用并行復(fù)制來(lái)加速?gòu)膸?kù)應(yīng)用binlog中的事件。
- 通過(guò)設(shè)置slave_parallel_workers參數(shù),可以指定并行工作線程的數(shù)量。
低版本的MySQL只支持單線程復(fù)制,如果主庫(kù)并發(fā)高,來(lái)不及傳送到從庫(kù),就會(huì)導(dǎo)致延遲??梢該Q用更高版本的Mysql,可以支持多線程復(fù)制。
2.8 業(yè)務(wù)側(cè)加緩存,優(yōu)化查詢
- 在業(yè)務(wù)側(cè)添加緩存層,如Redis、Memcached等,優(yōu)化查詢接口,以減少對(duì)數(shù)據(jù)庫(kù)的查詢壓力。
2.9 避免大表DDL操作
- 大表的DDL操作(如添加索引、修改表結(jié)構(gòu)等)會(huì)導(dǎo)致長(zhǎng)時(shí)間的鎖等待和復(fù)制延遲。
- 盡量避免在主從復(fù)制環(huán)境中對(duì)大表進(jìn)行DDL操作,或者選擇在業(yè)務(wù)低峰期進(jìn)行。