0 Github
1 面試題
- 有沒有做過MySQL讀寫分離
- 如何實(shí)現(xiàn)MySQL的讀寫分離
- 主從復(fù)制原理
- 如何解決MySQL主從同步的延時(shí)問題
準(zhǔn)備好面對(duì)這炮轟式面試了嗎?
2 考點(diǎn)分析
高并發(fā)階段,肯定需要做讀寫分離.
實(shí)際上大部分互聯(lián)網(wǎng)公司/網(wǎng)站/APP,都是讀多寫少
針對(duì)現(xiàn)狀,寫一個(gè)主庫,掛著多個(gè)從庫,然后從多個(gè)從庫來讀,那不就可以支撐更高的讀并發(fā)壓力了嗎?
3 MySQL讀寫分離的實(shí)現(xiàn)
基于主從復(fù)制架構(gòu)
搞一個(gè)主庫,掛多個(gè)從庫,然后就單單只是寫主庫,接著主庫會(huì)自動(dòng)將數(shù)據(jù)同步到從庫
4 MySQL主從復(fù)制的原理
-
為什么MySQL要讀寫分離?
image
主庫將變更寫binlog日志,然后從庫連接到主庫后,從庫有一個(gè)I/O線程,將主庫的binlog日志拷貝到本地,寫入一個(gè)中繼日志
接著從庫中有一個(gè)SQL線程會(huì)從中繼日志讀取binlog,然后執(zhí)行binlog日志中的內(nèi)容
即在本地再次執(zhí)行一遍SQL,確保跟主庫的數(shù)據(jù)相同
-
MySQL主從復(fù)制原理
image
從庫同步主庫數(shù)據(jù)的過程是串行化的,即主庫上并行的操作,在從庫上會(huì)串行執(zhí)行.
由于從庫從主庫拷貝日志以及串行執(zhí)行SQL的特點(diǎn),在高并發(fā)場(chǎng)景下是有延時(shí)的,從庫數(shù)據(jù)一定會(huì)比主庫慢一些,所以經(jīng)常出現(xiàn),剛寫入主庫的數(shù)據(jù)可能是讀不到的,要過幾十甚至幾百ms才能讀到
而且這里還有另外一個(gè)問題,若主庫突然宕機(jī),恰好數(shù)據(jù)還沒同步到從庫,那么有些數(shù)據(jù)可能在從庫上是沒有的,可能就這么丟失了
所以MySQL實(shí)際上在這有兩個(gè)機(jī)制
半同步復(fù)制(semi-sync)
解決主庫數(shù)據(jù)丟失問題
主庫寫入binlog日志后,就會(huì)強(qiáng)制此時(shí)立即將數(shù)據(jù)同步到從庫
從庫將日志寫入自己本地的relay log后,會(huì)返回一個(gè)ack給主庫
主庫接收到至少一個(gè)從庫的ack之后才會(huì)認(rèn)為寫操作完成
并行復(fù)制
解決主從同步延時(shí)問題
從庫開啟多個(gè)線程,并行讀取relay log中不同庫的日志,然后并行重放不同庫的日志,這是庫級(jí)別的并行
5 MySQL主從同步延時(shí)問題(核心)
-
MySQL主從延遲導(dǎo)致的生產(chǎn)環(huán)境的問題
image
你可以看到從庫復(fù)制主庫的數(shù)據(jù)落后了多少ms
其實(shí)這塊東西經(jīng)常會(huì)碰到,就比如說用了MySQL主從架構(gòu)后,可能會(huì)發(fā)現(xiàn),剛寫入庫的數(shù)據(jù)結(jié)果沒查到,結(jié)果就完蛋了
所以實(shí)際上你要考慮好應(yīng)該在什么場(chǎng)景下來用這個(gè)MySQL主從同步
建議一般在讀遠(yuǎn)遠(yuǎn)多于寫,且讀的時(shí)候一般對(duì)數(shù)據(jù)時(shí)效性要求沒那么高的時(shí)候采用
所以我們可以考慮的就是,你可以用MySQL的并行復(fù)制,但問題是那是庫級(jí)別的并行,所以有時(shí)候作用不是很大
此時(shí),通常來說,我們會(huì)對(duì)于那種寫后立馬就要保證可以查到的場(chǎng)景,采用強(qiáng)制讀主庫的方式
確保你肯定可以讀到數(shù)據(jù)。其實(shí)用一些數(shù)據(jù)庫中間件也是沒問題的。
一般若主從延遲較為嚴(yán)重
- 分庫 : 將一個(gè)主庫拆分為4個(gè)主庫,每個(gè)主庫的寫并發(fā)就500/s,此時(shí)主從延遲可忽略不計(jì)
- 打開MySQL支持的并行復(fù)制,多個(gè)庫并行復(fù)制,若某個(gè)庫的寫入并發(fā)特別高,寫并發(fā)達(dá)到了2000/s,并行復(fù)制還是沒意義。二八法則,很多時(shí)候比如說,就是少數(shù)的幾個(gè)訂單表,寫入了2000/s,其他幾十個(gè)表10/s
- 重寫代碼 : 寫代碼的同學(xué),要慎重,重寫一下代碼,插入數(shù)據(jù)之后,直接就更新,不要查詢
- 若確實(shí)存在必須先插入,立馬要求就查詢到,然后立馬就要反過來執(zhí)行一些操作,對(duì)這個(gè)查詢?cè)O(shè)置直連主庫(不推薦,這么搞導(dǎo)致讀寫分離的意義就喪失了)
參考
- 《Java工程師面試突擊第1季-中華石杉老師》