MySQL是怎麼保證高可用的?
正常情況下,只要主庫執行更新生成的所有binlog,都可以傳到備庫並被正確地執行,備庫就能達到跟主庫一致的狀態,這就是最終一致性。
但是,MySQL要提供高可用能力,只有最終一致性是不夠的。為什麼這麼說呢?今天我就著重和你分析一下。
這裡,我再放一次上一篇文章中講到的雙M結構的主備切換流程圖。
主備延遲
主備切換可能是一個主動運維動作,比如軟體升級、主庫所在機器按計劃下線等,也可能是被動操作,比如主庫所在機器掉電。
接下來,我們先一起看看主動切換的場景。
在介紹主動切換流程的詳細步驟之前,我要先跟你說明一個概念,即“同步延遲”。與資料同步有關的時間點主要包括以下三個:
-
主庫A執行完成一個事務,寫入binlog,我們把這個時刻記為T1;
-
之後傳給備庫B,我們把備庫B接收完這個binlog的時刻記為T2;
-
備庫B執行完成這個事務,我們把這個時刻記為T3。
所謂主備延遲,就是同一個事務,在備庫執行完成的時間和主庫執行完成的時間之間的差值,也就是T3-T1。
你可以在備庫上執行show slave status命令,它的返回結果裡面會顯示seconds_behind_master,用於表示當前備庫延遲了多少秒。
seconds_behind_master的計算方法是這樣的:
-
每個事務的binlog 裡面都有一個時間欄位,用於記錄主庫上寫入的時間;
-
備庫取出當前正在執行的事務的時間欄位的值,計算它與當前系統時間的差值,得到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資源,影響了同步速度,造成主備延遲。
這種情況,我們一般可以這麼處理:
-
一主多從。除了備庫外,可以多接幾個從庫,讓這些從庫來分擔讀的壓力。
-
通過binlog輸出到外部系統,比如Hadoop這類系統,讓外部系統提供統計類查詢的能力。
其中,一主多從的方式大都會被採用。因為作為資料庫系統,還必須保證有定期全量備份的能力。而從庫,就很適合用來做備份。
備註:這裡需要說明一下,從庫和備庫在概念上其實差不多。在我們這個專欄裡,為了方便描述,我把會在HA過程中被選成新主庫的,稱為備庫,其他的稱為從庫。
追問2:採用了一主多從,保證備庫的壓力不會超過主庫,還有什麼情況可能導致主備延遲嗎?
這就是第二種常見的可能了,即備庫的壓力大。一般的想法是,主庫既然提供了寫能力,那麼備庫可以提供一些讀能力。或者一些運營後臺需要的分析語句,不能影響正常業務,所以只能在備庫上跑。
我真就見過不少這樣的情況。由於主庫直接影響業務,大家使用起來會比較剋制,反而忽視了備庫的壓力控制。結果就是,備庫上的查詢耗費了大量的CPU資源,影響了同步速度,造成主備延遲。
這就是第三種可能了,即大事務。
大事務這種情況很好理解。因為主庫上必須等事務執行完成才會寫入binlog,再傳給備庫。所以,如果一個主庫上的語句執行10分鐘,那這個事務很可能就會導致從庫延遲10分鐘。
不知道你所在公司的DBA有沒有跟你這麼說過:不要一次性地用delete語句刪除太多資料。其實,這就是一個典型的大事務場景。
比如,一些歸檔類的資料,平時沒有注意刪除歷史資料,等到空間快滿了,業務開發人員要一次性地刪掉大量歷史資料。同時,又因為要避免在高峰期操作會影響業務(至少有這個意識還是很不錯的),所以會在晚上執行這些大量資料的刪除操作。
結果,負責的DBA同學半夜就會收到延遲報警。然後,DBA團隊就要求你後續再刪除資料的時候,要控制每個事務刪除的資料量,分成多次刪除
追問3:如果主庫上也不做大事務了,還有什麼原因會導致主備延遲嗎?
由於主備延遲的存在,所以在主備切換的時候,就相應的有不同的策略。