Mysql Replication 簡明教程

學習也好,分析問題也好,都要有系統思維。

當別人還停留在只有一個Mysql實例的認知時,你要知道,其實生產環境的Mysql,最起碼也應該長這樣:

from https://dev.mysql.com/doc/refman/5.7/en/replication-solutions-switch.html

為什么要主從

幾乎每個上了生產環境的系統,都不可能是單機的,通常都采用了主從架構。

而為什么要采用主從,只需記住這幾個關鍵字:SPOF讀寫分離BackupScale-Out

歸納一下,其實就兩點。

1、
防止SPOF:SPOF,single point of failure,如果你只有一個Mysql實例,那么它的死亡,就意味著你數據庫服務的終止,也就意味著你整個系統的奔潰。但是如果你掛了一個Mysql,還有千千萬萬個Mysql頂上去,那就稍微牛B些了。

2、
讀寫分離:通常我們的業務,都是讀多于寫,這時候就可以把寫交給Master,把讀交給其他的Slave。

比如你想要備份(backup)數據,如果直接在Master上執行mysqldump,很明顯,會影響到線上的寫操作,這時候就可以找一臺slave,安安靜靜的執行;

比如你發現讀請求越來越多了,這時候只需要加多幾臺Slave,來分擔下讀請求,這就是Scale-Out,拓展性

又比如,你想對數據進行分析,統計一下最近幾天各種類型的訂單數量,這時候,在一臺Slave上默默操作,或者從一臺Slave上,把數據導出到hadoop,交給hadoop去分析,都可以。

兩個動作

每個支持主從架構的系統,都要考慮要如何實現兩個動作:主從復制主從切換

平時數據要從Master復制到各個Slave;而在Master宕機時,則要進行主從切換,將Master切換到其中一臺Slave上。

下面就來聊聊Mysql是如何實現這兩個動作的。

主從復制

Master寫入數據后,需要把數據同步給Slave,這就是主從復制。

那么Master把這些數據,以什么樣的協議、格式發給Slave呢?由于不同系統的功能不同,他們用于存儲數據的數據結構也不同,所以,他們之間的復制方式也各有差異。

比如redis,發的就是rdb或者aof文件,而Mysql,則發的是bin log。

bin log有三種格式,statement/row/mixed ,具體可以參考 Replication Formats

那么bin log又是如何從Master發給Slave,又是如何被Slave執行的呢?

Mysql用了三個線程,來實現這個過程,一個在Master,兩個在Slave:

  • Binlog dump thread:負責把bin log發給slave
  • Slave I/O thread:負責接收master發過來的bin log,并把它暫時存放在一個叫relay log的日志文件
  • Slave SQL thread:讀取relay log,執行里面的內容

至于為什么mysql要這么設計,其實仔細觀察,就會發現這整個過程,有點像消息中間件處理消息的過程,所以問題就變成我之前寫的另一篇文章:為什么要使用消息中間件

你看,知識是互通的

主從延遲

在講主從切換之前,我們來聊下主從延遲。

有主從的系統,都會有延遲,那種在Master寫入后,Slave馬上同步發生變化的事情,想想就知道,是不存在的。

那么導致主從延遲的原因有哪些呢?

可能是Slave機器性能太差,在Master執行1s的語句,在Slave要執行5s,通常在經濟拮據的公司就會這么干,搞一臺很一般的機器,來做Slave;

咱們不差錢,那就讓Slave的機器和Master一樣優秀。

可是這樣還是主從延遲很大,為啥?

噢,原來咱們把太多的查詢分析業務放slave了,各個業務端,在分析數據時,為了不影響Master,都選擇走Slave,Slave壓力太大,自然延遲了。

于是我們有了一主多從,Slave你不是忙不過來嗎,那我給你找多幾個幫手。

這下應該延遲會小了吧?

并沒有,我們發現系統偶爾還是會有很大延遲,查了很久,發現是Slave在執行一個耗時10s的事務,等執行完commit時,Slave已經延遲了10s。

這下知道為什么盡量不要寫大事務了吧。

主從切換

現在可以來講「主從切換」了。

正因為有上面的「主從延遲」,才有了當Master宕機時,我們在一致性和可用性之間尋求優先級的糾結。

其實也就是CAP理論里經常遇到的選擇,在P(分區容忍性)必須滿足的情況下,到底是選擇C(強一致性)還是A(可用性)。

from https://dev.mysql.com/doc/refman/5.7/en/replication-solutions-switch.html

如果要保證強一致性,那么切換時就有這幾個步驟:

  • 把原來的Master,設置為read-only = true,這個時刻記為time1;
  • 等待Slave執行完Master發給它的bin log,直到Slave和Master一致,這個時刻記為time2;
  • 現在一致了,可以把slave設置為read-only = false,即可寫入

在這個過程中,從time1到time2的時間,系統是無法被寫入的,即不可用。

這個不可用的時間,取決于切換的時候,slave和master的延遲時間,延遲的越長,同步完成需要的時間就越長,不可用的時間也就越長。

保證強一致性,就會犧牲可用性,如果你不想系統有不可用的時間呢?那就得犧牲強一致性,因為你必須在Slave和Master還沒完全同步時,就把Slave切換為Master。

主從數據不一致,會有什么問題呢?思考題。

總結

這篇文章只是在講Mysql的主從嗎?

我們總會說,技術那么多,還日新月異的,好像每天都有新的很厲害的技術出來,學不動。

但其實,如果學一項技術,就只是在學一項技術,而不去舉一反三,發現知識背后通用的規則,那你之前學的知識,就只是在占用你大腦的內存,對你之后學的東西,沒任何幫助。

但是如果你可以把所學的知識,串起來,形成一個體系,用系統的角度去看他們,那就不一樣了。

比如今天我學了Mysql主從,那么當我們下次在學習其他系統的主從架構時,比如說redis,就可以照著今天這個思路去學習:

  • redis的主從架構長什么樣子?
  • redis主從之間如何進行復制,數據格式是怎么樣的?
  • redis主從延遲的原因有哪些?
  • master宕機時,redis如何進行主從切換?
  • ...

知識都是通的。

留個問題

現在我們學會用「主從」的角度來看待mysql,而不再是一個獨立的機器。

有什么用呢?留個問題好了。

我們在業務中經常會用到外鍵,比如有兩張表,一張是「方案表 plan」,另一種是「方案適用員工表 plan_staff」,plan_staff里有一個字段,plan_id,指向了plan表的主鍵,這樣做,有問題嗎?

參考

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容