1. 程式人生 > 其它 >MySQL是怎麼保證高可用的?

MySQL是怎麼保證高可用的?

正常情況下,只要主庫執行更新生成的所有binlog,都可以傳到備庫並被正確地執行,備庫就能達到跟主庫一致的狀態,這就是最終一致性。

但是,MySQL要提供高可用能力,只有最終一致性是不夠的。為什麼這麼說呢?今天我就著重和你分析一下。

這裡,我再放一次上一篇文章中講到的雙M結構的主備切換流程圖。

主備延遲

主備切換可能是一個主動運維動作,比如軟體升級、主庫所在機器按計劃下線等,也可能是被動操作,比如主庫所在機器掉電。

接下來,我們先一起看看主動切換的場景。

在介紹主動切換流程的詳細步驟之前,我要先跟你說明一個概念,即“同步延遲”。與資料同步有關的時間點主要包括以下三個:

  1. 主庫A執行完成一個事務,寫入binlog,我們把這個時刻記為T1;

  2. 之後傳給備庫B,我們把備庫B接收完這個binlog的時刻記為T2;

  3. 備庫B執行完成這個事務,我們把這個時刻記為T3。

所謂主備延遲,就是同一個事務,在備庫執行完成的時間和主庫執行完成的時間之間的差值,也就是T3-T1

你可以在備庫上執行show slave status命令,它的返回結果裡面會顯示seconds_behind_master,用於表示當前備庫延遲了多少秒。

seconds_behind_master的計算方法是這樣的:

  1. 每個事務的binlog 裡面都有一個時間欄位,用於記錄主庫上寫入的時間;

  2. 備庫取出當前正在執行的事務的時間欄位的值,計算它與當前系統時間的差值,得到seconds_behind_master。

可以看到,其實seconds_behind_master這個引數計算的就是T3-T1。所以,我們可以用seconds_behind_master來作為主備延遲的值,這個值的時間精度是秒。

你可能會問,如果主備庫機器的系統時間設定不一致,會不會導致主備延遲的值不準?

其實不會的。因為,備庫連線到主庫的時候,會通過執行SELECT UNIX_TIMESTAMP()函式來獲得當前主庫的系統時間。如果這時候發現主庫的系統時間與自己不一致,備庫在執行seconds_behind_master計算的時候會自動扣掉這個差值。

需要說明的是,在網路正常的時候,日誌從主庫傳給備庫所需的時間是很短的,即T2-T1的值是非常小的。也就是說,網路正常情況下,主備延遲的主要來源是備庫接收完binlog和執行完這個事務之間

的時間差。

主備延遲的來源

首先,有些部署條件下,備庫所在機器的效能要比主庫所在的機器效能差。

一般情況下,有人這麼部署時的想法是,反正備庫沒有請求,所以可以用差一點兒的機器。或者,他們會把20個主庫放在4臺機器上,而把備庫集中在一臺機器上。

其實我們都知道,更新請求對IOPS的壓力,在主庫和備庫上是無差別的。所以,做這種部署時,一般都會將備庫設定為“非雙1”的模式。

但實際上,更新過程中也會觸發大量的讀操作。所以,當備庫主機上的多個備庫都在爭搶資源的時候,就可能會導致主備延遲了。

當然,這種部署現在比較少了。因為主備可能發生切換,備庫隨時可能變成主庫,所以主備庫選用相同規格的機器,並且做對稱部署,是現在比較常見的情況。

追問1:但是,做了對稱部署以後,還可能會有延遲。這是為什麼呢?

這就是第二種常見的可能了,即備庫的壓力大。一般的想法是,主庫既然提供了寫能力,那麼備庫可以提供一些讀能力。或者一些運營後臺需要的分析語句,不能影響正常業務,所以只能在備庫上跑。

我真就見過不少這樣的情況。由於主庫直接影響業務,大家使用起來會比較剋制,反而忽視了備庫的壓力控制。結果就是,備庫上的查詢耗費了大量的CPU資源,影響了同步速度,造成主備延遲。

這種情況,我們一般可以這麼處理:

  1. 一主多從。除了備庫外,可以多接幾個從庫,讓這些從庫來分擔讀的壓力

  2. 通過binlog輸出到外部系統,比如Hadoop這類系統,讓外部系統提供統計類查詢的能力。

其中,一主多從的方式大都會被採用。因為作為資料庫系統,還必須保證有定期全量備份的能力。而從庫,就很適合用來做備份。

備註:這裡需要說明一下,從庫和備庫在概念上其實差不多。在我們這個專欄裡,為了方便描述,我把會在HA過程中被選成新主庫的,稱為備庫,其他的稱為從庫。

追問2:採用了一主多從,保證備庫的壓力不會超過主庫,還有什麼情況可能導致主備延遲嗎?

這就是第二種常見的可能了,即備庫的壓力大。一般的想法是,主庫既然提供了寫能力,那麼備庫可以提供一些讀能力。或者一些運營後臺需要的分析語句,不能影響正常業務,所以只能在備庫上跑。

我真就見過不少這樣的情況。由於主庫直接影響業務,大家使用起來會比較剋制,反而忽視了備庫的壓力控制。結果就是,備庫上的查詢耗費了大量的CPU資源,影響了同步速度,造成主備延遲

這就是第三種可能了,即大事務。

大事務這種情況很好理解。因為主庫上必須等事務執行完成才會寫入binlog,再傳給備庫。所以,如果一個主庫上的語句執行10分鐘,那這個事務很可能就會導致從庫延遲10分鐘。

不知道你所在公司的DBA有沒有跟你這麼說過:不要一次性地用delete語句刪除太多資料。其實,這就是一個典型的大事務場景。

比如,一些歸檔類的資料,平時沒有注意刪除歷史資料,等到空間快滿了,業務開發人員要一次性地刪掉大量歷史資料。同時,又因為要避免在高峰期操作會影響業務(至少有這個意識還是很不錯的),所以會在晚上執行這些大量資料的刪除操作。

結果,負責的DBA同學半夜就會收到延遲報警。然後,DBA團隊就要求你後續再刪除資料的時候,要控制每個事務刪除的資料量,分成多次刪除

追問3:如果主庫上也不做大事務了,還有什麼原因會導致主備延遲嗎?

由於主備延遲的存在,所以在主備切換的時候,就相應的有不同的策略。