天天看點

MySQL雙主一緻性架構優化 | 架構師之路

一、雙主保證高可用

MySQL資料庫叢集常使用一主多從,主從同步,讀寫分離的方式來擴充資料庫的讀性能,保證讀庫的高可用,但此時寫庫仍然是單點。

在一個MySQL資料庫叢集中可以設定兩個主庫,并設定雙向同步,以備援寫庫的方式來保證寫庫的高可用。

二、并發引發不一緻

資料備援會引發資料的一緻性問題,因為資料的同步有一個時間差,并發的寫入可能導緻資料同步失敗,引起資料丢失:

MySQL雙主一緻性架構優化 | 架構師之路

如上圖所述,假設主庫使用了auto increment來作為自增主鍵:

兩個MySQL-master設定雙向同步可以用來保證主庫的高可用

資料庫中現存的記錄主鍵是1,2,3

主庫1插入了一條記錄,主鍵為4,并向主庫2同步資料

資料同步成功之前,主庫2也插入了一條記錄,由于資料還沒有同步成功,插入記錄生成的主鍵也為4,并向主庫1也同步資料

主庫1和主庫2都插入了主鍵為4的記錄,雙主同步失敗,資料不一緻

三、相同步長免沖突

能否保證兩個主庫生成的主鍵一定不沖突呢?

回答:

設定不同的初始值

設定相同的增長步長

就能夠做到。

MySQL雙主一緻性架構優化 | 架構師之路

如上圖所示:

庫1的自增初始值是1,庫2的自增初始值是2,增長步長都為2

庫1中插入資料主鍵為1/3/5/7,庫2中插入資料主鍵為2/4/6/8,不沖突

資料雙向同步後,兩個主庫會包含全部資料

MySQL雙主一緻性架構優化 | 架構師之路

如上圖所示,兩個主庫最終都将包含1/2/3/4/5/6/7/8所有資料,即使有一個主庫挂了,另一個主庫也能夠保證寫庫的高可用。

四、上遊生成ID避沖突

換一個思路,為何要依賴于資料庫的自增ID,來保證資料的一緻性呢?

完全可以由業務上遊,使用統一的ID生成器,來保證ID的生成不沖突:

MySQL雙主一緻性架構優化 | 架構師之路

如上圖所示,調用方插入資料時,帶入全局唯一ID,而不依賴于資料庫的auto increment,也能解決這個問題。

至于如何生成全局唯一,趨勢遞增的ID,參見文章《分布式ID生成算法》。

五、消除雙寫不治本

使用auto increment兩個主庫并發寫可能導緻資料不一緻,隻使用一個主庫提供服務,另一個主庫作為shadow-master,隻用來保證高可用,能否避免一緻性問題呢?

MySQL雙主一緻性架構優化 | 架構師之路

隻有主庫1對外提供寫入服務

兩個主庫設定相同的虛IP,在主庫1挂掉或者網絡異常的時候,虛IP自動漂移,shadow master頂上,保證主庫的高可用

這個切換由于虛IP沒有變化,是以切換過程對調用方是透明的,但在極限的情況下,也可能引發資料的不一緻:

MySQL雙主一緻性架構優化 | 架構師之路

兩個MySQL-master設定雙向同步可以用來保證主庫的高可用,并設定了相同的虛IP

網絡抖動前,主庫1對上遊提供寫入服務,插入了一條記錄,主鍵為4,并向shadow master主庫2同步資料

突然主庫1網絡異常,keepalived檢測出異常後,實施虛IP漂移,主庫2開始提供服務

在主鍵4的資料同步成功之前,主庫2插入了一條記錄,也生成了主鍵為4的記錄,結果導緻資料不一緻

六、内網DNS探測

虛IP漂移,雙主同步延時導緻的資料不一緻,本質上,需要在雙主同步完資料之後,再實施虛IP偏移,使用内網DNS探測,可以實作shadow master延時高可用:

使用内網域名連接配接資料庫,例如:db.58daojia.org

主庫1和主庫2設定雙主同步,不使用相同虛IP,而是分别使用ip1和ip2

一開始db.58daojia.org指向ip1

用一個小腳本輪詢探測ip1主庫的連通性

當ip1主庫發生異常時,小腳本delay一個x秒的延時,等待主庫2同步完資料之後,再将db.58daojia.org解析到ip2

程式以内網域名進行重連,即可自動連接配接到ip2主庫,并保證了資料的一緻性

七、總結

主庫高可用,主庫一緻性,一些小技巧:

雙主同步是一種常見的保證寫庫高可用的方式

設定相同步長,不同初始值,可以避免auto increment生成沖突主鍵

不依賴資料庫,業務調用方自己生成全局唯一ID是一個好方法

shadow master保證寫庫高可用,隻有一個寫庫提供服務,并不能完全保證一緻性

内網DNS探測,可以實作在主庫1出現問題後,延時一個時間,再進行主庫切換,以保證資料一緻性