說說 MySQL 主從數據同步機制

最近有小夥伴拿到了一線互聯網企業如滴滴、阿里、汽車之家、極兔、有贊、希音、百度、網易、滴滴的面試資格,遇到一幾個很重要的面試題:

  • 說說 MySQL 主從同步的流程

  • 說說 MySQL 主從同步的幾種方式

主從同步的重要性:

所以,這裏給大家做一下系統化、體系化的梳理,使得大家可以充分展示一下大家雄厚的 “技術肌肉”,讓面試官愛到 “不能自已、口水直流”

本文目錄

    - 1、異步複製

    - 2、同步複製

    - 3、半同步複製

一、MySQL 主從同步流程

當客戶端提交一個事務到 MySQL 的集羣,直到客戶端收到集羣返回成功響應,在這個過程中,MySQL 集羣需要執行很多操作:

注意:請點擊圖像以查看清晰的視圖!

這些操作的時序非常重要,這裏面的時序,說的就是這些操作的先後順序。同樣的操作,因爲時序不同,對應用程序來說,有很大的差異。

比如說,如果先複製 Binlog,等 Binlog 複製到從節點上之後,主節點再去提交事務,這種情況下,從節點的 Binlog 一直和主節點是同步的,任何情況下主節點宕機也不會丟數據。

然而,若將時序顛倒,先提交事務再複製  Binlog,性能將大幅提升,但數據丟失的風險也會增加。

MySQL 提供了幾個參數來配置這個時序,我們先看一下默認情況下的時序是什麼樣的。

二、主從同步的三種方式

1、異步複製

默認情況下,MySQL 採用異步複製的方式,執行事務操作的線程不會等複製 Binlog 的線程。

注意:請點擊圖像以查看清晰的視圖!

在客戶端向 MySQL 主庫提交事務請求後,主庫會先將事務記錄到 Binlog,然後提交事務,更新存儲引擎的數據,事務提交成功後,返回成功響應給客戶端。

同時,從庫會開啓一個專門的複製線程,接收主庫的 Binlog,並將其寫入中繼日誌,然後向主庫返回複製成功的響應。

此外,從庫還有一個回放 Binlog 的線程,用於讀取中繼日誌並回放 Binlog 以更新存儲引擎的數據,這個過程與我們今天討論的主從複製關係無關,因此在圖中沒有展示。

提交事務和複製這兩個流程在不同的線程中獨立執行,互不等待,這就是異步複製。

理解了異步複製的順序後,我們就能更容易地理解之前幾節課中提到的一些問題的原因。

例如,在異步複製下,爲什麼主庫宕機會有數據丟失的風險?爲什麼讀寫分離會有讀到髒數據的問題?

這些問題的產生,都是因爲異步複製無法保證數據能第一時間複製到從庫上。

異步複製的優點是性能優越,但缺點是數據安全性較差。在某一時刻,主從之間的數據差異可能較大,如果主機崩潰,從機接管時可能會丟失一部分數據。

2、同步複製

全同步複製跟半同步複製的區別是,全同步複製必須收到所有從庫的 ack,纔會提交事務。

同步複製這種方式在實際項目中,基本上沒法用,原因有兩個:

全同步複製的數據一致性最好,但是性能也是最差的。

3、半同步複製

爲了解決這個問題,MySQL 從 5.7 版本開始,增加一種 半同步複製(Semisynchronous Replication)的方式。

在 master 更新操作寫入 Binlog 後,會主動通知 slave,slave 接收到後寫入 Relay Log 即可迴應。master 只需收到至少一個 ACK 應答,便可提交事務。

可以發現,相較於異步複製,半同步複製需要至少一個 slave 將 Binlog 寫入 Relay Log,這在一定程度上降低了性能,但能夠確保至少有一個從庫與 master 的數據保持一致,從而提高數據安全性。

注意:請點擊圖像以查看清晰的視圖!

半同步複製兼顧了異步複製和同步複製的優點。如果主庫宕機,至少還有一個從庫擁有最新數據,不會出現數據丟失的風險。

並且,半同步複製的性能也還湊合,也能提供高可用保證,從庫宕機也不會影響主庫提供服務。因此,這種折衷的複製方式半同步複製,也是一種不錯的選擇。

三、半同步複製的注意問題

接下來,將向大家介紹,在實際應用中選擇半同步複製時需要特別關注的幾個問題。

在配置半同步複製時,有一個關鍵參數 rpl_semi_sync_master_wait_no_slave,其含義是:「等待至少幾個從節點完成數據複製後再返回」。

該參數設置的值越大,數據丟失的風險越小,但集羣的性能和可用性會相應降低。最大值可以設置爲與從節點數量相同,這樣就變成了同步複製。

通常情況下,使用默認值 1 即可,這樣可以最大程度地減小性能損失,同時保證高可用性。只要還有一個從庫正常運行,就不會影響主庫的讀寫操作。數據丟失的風險也較小,除非主庫和擁有最新數據的從庫同時出現問題,纔有可能發生數據丟失。

另一個重要的參數是 rpl_semi_sync_master_wait_point,它控制主庫執行事務的線程是在提交事務之前(AFTER_SYNC)等待複製,還是在提交事務之後(AFTER_COMMIT)等待複製。默認值爲 AFTER_SYNC,即先等待複製,再提交事務,這樣可以確保不丟失任何數據。AFTER_COMMIT 具有更好的性能,不會長時間鎖定表,但仍然存在因主機崩潰而導致數據丟失的風險。

此外,儘管我們設置了同步或半同步複製,並等待複製成功後再提交事務,但仍然存在一種容易被忽視、可能引發數據丟失風險的情況。

如果主庫提交事務的線程等待複製的時間超過設定的閾值,事務仍然會被正常提交。此外,MySQL 會自動降級爲異步複製模式,直到有足夠多(rpl_semi_sync_master_wait_no_slave)的從庫追趕上主庫,才能恢復爲半同步複製。如果在此期間主庫崩潰,仍然存在數據丟失的風險。

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