天天看點

突破Java面試(50)-MySQL讀寫分離及主從同步延時解決方案0 Github 1 面試題2 考點分析3 MySQL讀寫分離的實作4 MySQL主從複制的原理5 MySQL主從同步延時問題(核心)參考

Github

1 面試題

  • 有沒有做過MySQL讀寫分離
  • 如何實作MySQL的讀寫分離
  • 主從複制原理
  • 如何解決MySQL主從同步的延時問題

準備好面對這炮轟式面試了嗎?

2 考點分析

高并發階段,肯定需要做讀寫分離.

實際上大部分網際網路公司/網站/APP,都是讀多寫少

針對現狀,寫一個主庫,挂着多個從庫,然後從多個從庫來讀,那不就可以支撐更高的讀并發壓力了嗎?

3 MySQL讀寫分離的實作

基于主從複制架構

搞一個主庫,挂多個從庫,然後就單單隻是寫主庫,接着主庫會自動将資料同步到從庫

4 MySQL主從複制的原理

  • 為什麼MySQL要讀寫分離?

主庫将變更寫binlog日志,然後從庫連接配接到主庫後,從庫有一個I/O線程,将主庫的binlog日志拷貝到本地,寫入一個中繼日志

接着從庫中有一個SQL線程會從中繼日志讀取binlog,然後執行binlog日志中的内容

即在本地再次執行一遍SQL,確定跟主庫的資料相同

  • MySQL主從複制原理

從庫同步主庫資料的過程是串行化的,即主庫上并行的操作,在從庫上會串行執行.

由于從庫從主庫拷貝日志以及串行執行SQL的特點,在高并發場景下是有延時的,從庫資料一定會比主庫慢一些,是以經常出現,剛寫入主庫的資料可能是讀不到的,要過幾十甚至幾百ms才能讀到

而且這裡還有另外一個問題,若主庫突然當機,恰好資料還沒同步到從庫,那麼有些資料可能在從庫上是沒有的,可能就這麼丢失了

是以MySQL實際上在這有兩個機制

半同步複制(semi-sync)

解決主庫資料丢失問題

主庫寫入binlog日志後,就會強制此時立即将資料同步到從庫

從庫将日志寫入自己本地的relay log後,會傳回一個ack給主庫

主庫接收到至少一個從庫的ack之後才會認為寫操作完成

并行複制

解決主從同步延時問題

從庫開啟多個線程,并行讀取relay log中不同庫的日志,然後并行重放不同庫的日志,這是庫級别的并行

5 MySQL主從同步延時問題(核心)

  • MySQL主從延遲導緻的生産環境的問題
show status,Seconds_Behind_Master           

你可以看到從庫複制主庫的資料落後了多少ms

其實這塊東西經常會碰到,就比如說用了MySQL主從架構後,可能會發現,剛寫入庫的資料結果沒查到,結果就完蛋了

是以實際上你要考慮好應該在什麼場景下來用這個MySQL主從同步

建議一般在讀遠遠多于寫,且讀的時候一般對資料時效性要求沒那麼高的時候采用

是以我們可以考慮的就是,你可以用MySQL的并行複制,但問題是那是庫級别的并行,是以有時候作用不是很大

此時,通常來說,我們會對于那種寫後立馬就要保證可以查到的場景,采用強制讀主庫的方式

確定你肯定可以讀到資料。其實用一些資料庫中間件也是沒問題的。

一般若主從延遲較為嚴重

  1. 分庫 : 将一個主庫拆分為4個主庫,每個主庫的寫并發就500/s,此時主從延遲可忽略不計
  2. 打開MySQL支援的并行複制,多個庫并行複制,若某個庫的寫入并發特别高,寫并發達到了2000/s,并行複制還是沒意義。二八法則,很多時候比如說,就是少數的幾個訂單表,寫入了2000/s,其他幾十個表10/s
  3. 重寫代碼 : 寫代碼的同學,要慎重,重寫一下代碼,插入資料之後,直接就更新,不要查詢
  4. 若确實存在必須先插入,立馬要求就查詢到,然後立馬就要反過來執行一些操作,對這個查詢設定直連主庫(不推薦,這麼搞導緻讀寫分離的意義就喪失了)

參考

  • 《Java工程師面試突擊第1季-中華石杉老師》