MySQL 主從,6 分鐘帶你掌握!

大家好,我是樓仔!

MySQL 主從一直是面試常客,裏面的知識點雖然基礎,但是能回答全的同學不多。

比如我之前面試小米,就被問到過主從複製的原理,以及主從延遲的解決方案,你之前面試,有遇到過哪些 MySQL 主從的問題呢?

文章很多內容參考田螺哥的文章,詳見參考文章,特此說明!

1. MySQL 主從

1.1 什麼是 MySQL 主從 ?

所謂 MySQL 主從,就是建立兩個完全一樣的數據庫,一個是主庫,一個是從庫,主庫對外提供讀寫的操作,從庫對外提供讀的操作

1.2 爲什麼使用 MySQL 主從 ?

對於數據庫單機部署,在 4 核 8G 的機器上運行 MySQL 5.7 時,大概可以支撐 500 的 TPS 和 10000 的 QPS,當遇到一些活動時,查詢流量驟然,就需要進行主從分離。

大部分系統的訪問模型是讀多寫少,讀寫請求量的差距可能達到幾個數量級,所以我們可以通過一主多從的方式,主庫只負責寫入和部分核心邏輯的查詢,多個從庫只負責查詢,提升查詢性能,降低主庫壓力。

當主庫宕機時,從庫可以切成主庫,保證服務的高可用,然後主庫也可以做數據的容災備份,整體場景總結如下:

2. 主從複製

2.1 主從複製原理

MySQL 的主從複製是依賴於 binlog,也就是記錄 MySQL 上的所有變化並以二進制形式保存在磁盤上二進制日誌文件。

主從複製就是將 binlog 中的數據從主庫傳輸到從庫上,一般這個過程是異步的,即主庫上的操作不會等待 binlog 同步地完成。

詳細流程如下:

  1. 主庫寫 binlog:主庫的更新 SQL(update、insert、delete) 被寫到 binlog;

  2. 主庫發送 binlog:主庫創建一個 log dump 線程來發送 binlog 給從庫;

  3. 從庫寫 relay log:從庫在連接到主節點時會創建一個 IO 線程,以請求主庫更新的 binlog,並且把接收到的 binlog 信息寫入一個叫做 relay log 的日誌文件;

  4. 從庫回放:從庫還會創建一個 SQL 線程讀取 relay log 中的內容,並且在從庫中做回放,最終實現主從的一致性。

2.2 如何保證主從一致

當主庫和從庫數據同步時,突然中斷怎麼辦?因爲主庫與從庫之間維持了一個長鏈接,主庫內部有一個線程,專門服務於從庫的這個長鏈接。

對於下面的情況,假如主庫執行如下 SQL,其中 a 和 create_time 都是索引:

delete from t where a > '666' and create_time<'2022-03-01' limit 1;

我們知道,數據選擇了 a 索引和選擇 create_time 索引,最後 limit 1 出來的數據一般是不一樣的。

所以就會存在這種情況:在 binlog = statement 格式時,主庫在執行這條 SQL 時,使用的是索引 a,而從庫在執行這條 SQL 時,使用了索引 create_time,最後主從數據不一致了。

那麼我們該如何解決呢?

可以把 binlog 格式修改爲 row,row 格式的 binlog 日誌記錄的不是 SQL 原文,而是兩個 event:Table_map 和 Delete_rows。

Table_map event 說明要操作的表,Delete_rows event 用於定義要刪除的行爲,記錄刪除的具體行數。row 格式的 binlog 記錄的就是要刪除的主鍵 ID 信息,因此不會出現主從不一致的問題。

但是如果 SQL 刪除 10 萬行數據,使用 row 格式就會很佔空間,10 萬條數據都在 binlog 裏面,寫 binlog 的時候也很耗 IO。但是 statement 格式的 binlog 可能會導致數據不一致。

設計 MySQL 的大叔想了一個折中的方案,mixed 格式的 binlog,其實就是 row 和 statement 格式混合使用,當 MySQL 判斷可能數據不一致時,就用 row 格式,否則使用就用 statement 格式。

3. 主從延遲

有時候我們遇到從數據庫中獲取不到信息的詭異問題時,會糾結於代碼中是否有一些邏輯會把之前寫入的內容刪除,但是你又會發現,過了一段時間再去查詢時又可以讀到數據了,這基本上就是主從延遲在作怪。

主從延遲,其實就是 “從庫回放” 完成的時間,與 “主庫寫 binlog” 完成時間的差值,會導致從庫查詢的數據,和主庫的不一致

3.1 主從延遲原理

談到 MySQL 數據庫主從同步延遲原理,得從 MySQL 的主從複製原理說起:

總結一下主從延遲的主要原因:主從延遲主要是出現在 “relay log 回放” 這一步,當主庫的 TPS 併發較高,產生的 DDL 數量超過從庫一個 SQL 線程所能承受的範圍,那麼延時就產生了,當然還有就是可能與從庫的大型 query 語句產生了鎖等待。

3.2 主從延遲情況

3.3 主從延遲解決方案

我們一般會把從庫落後的時間作爲一個重點的數據庫指標做監控和報警,正常的時間是在毫秒級別,一旦落後的時間達到了秒級別就需要告警了。

解決該問題的方法,除了縮短主從延遲的時間,還有一些其它的方法,基本原理都是儘量不查詢從庫,具體解決方案如下:

在實際應用場景中,對於一些非常核心的場景,比如庫存,支付訂單等,需要直接查詢主庫,其它非核心場景,就不要去查主庫了。

4. 主從切換

4.1 一主一從

兩臺機器 A 和 B,A 爲主庫,負責讀寫,B 爲從庫,負責讀數據。

如果 A 庫發生故障,B 庫成爲主庫負責讀寫,修復故障後,A 成爲從庫,主庫 B 同步數據到從庫 A。

對於一主一從的模式,一般小公司會這麼用,不過該模式下,主從分離的意義其實並不大,因爲小公司的流量不高,更多是爲了數據庫的可用性,以及數據備份。

4.2 一主多從

一臺主庫多臺從庫,A 爲主庫,負責讀寫,B、C、D 爲從庫,負責讀數據。

如果 A 庫發生故障,B 庫成爲主庫負責讀寫,C、D 負責讀,修復故障後,A 也成爲從庫,主庫 B 同步數據到從庫 A。

基本上大公司,比如百度、滴滴,都是這種一主多從的模式,因爲查詢流量太高,一定需要進行讀寫分離,同時也需要支持服務的高可用、數據容災。

再結合上一篇文章講的分庫分表,基本就是大公司的標配了。

參考資料

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/0uhM2jptAogSRHMc3sopbQ