目錄前言單一IDC多IDCmysql主從同步資料同步方案多機房mysql同步方案最佳化同步方案同步方案的問題如何解決重複插入對於DDL語句處理如何解決唯一索引衝突如何解決資料迴環問題總結前言
小夥伴們是否經常聽說多機房部署,異地容災?什麼兩地3中心,三地5中心?是否好奇多機房部署,資料之間是如何共享的呢?
今天老顧就來嘗試著給大家解惑解惑,並詳細介紹一下資料同步的問題。
單一IDC上圖的架構,是一個IDC機房中,部署了一主兩從mysql資料庫叢集,大多資料中小型網際網路公司採用的方案。
上面的方案存在一些問題:
1)不同地區的使用者體驗速度不同。一個IDC必然只能部署在一個地區,例如部署在北京,那麼北京的使用者訪問將會得到快速響應;但是對於上海的使用者,訪問延遲一般就會大一點。
上海到北京的一個RTT可能有20ms左右。
2)容災問題。這裡容災不是單臺機器故障,而是指機房斷電,自然災害,或者光纖被挖斷等重大災害。一旦出現這種問題,將無法正常為使用者提供訪問,甚至出現數據丟失的情況。
某年,支付寶杭州某資料中心的光纜就被挖斷過
多IDC為了解決這些問題,我們可以將服務部署到多個不同的IDC中,不同IDC之間的資料互相進行同步。如下圖
透過這種方式,我們可以解決單機房遇到的問題:
1)使用者體驗。不同的使用者可以選擇離自己最近的機房進行訪問
2)容災問題。當一個機房掛了之後,我們可以將這個機房使用者的流量排程到另外一個正常的機房,由於不同機房之間的資料是實時同步的,使用者流量排程過去後,也可以正常訪問資料
故障發生那一刻的少部分資料可能會丟失
關於流量的排程問題,本文就不介紹,以後老顧會單獨介紹流量、灰度釋出的問題。本文主要介紹資料同步。
容災補充機房容災 : 上面的案例中,我們使用了2個IDC,但是2個IDC並不能具備機房容災能力。至少需要3個IDC,例如,一些基於多數派協議的一致性元件,如zookeeper,redis、etcd、consul等,需要得到大部分節點的同意。例如我們部署了3個節點,在只有2個機房的情況下, 必然是一個機房部署2個節點,一個機房部署一個節點。當部署了2個節點的機房掛了之後,只剩下一個節點,無法形成多數派。在3機房的情況下,每個機房部署一個節點,任意一個機房掛了,還剩2個節點,還是可以形成多數派。這也就是我們常說的"兩地三中心”。城市級容災:在發生重大自然災害的情況下,可能整個城市的機房都無法訪問。為了達到城市級容災的能力,使用的是"三地五中心"的方案。這種情況下,3個城市分別擁有2、2、1個機房。當整個城市發生災難時,其他兩個城市依然至少可以保證有3個機房依然是存活的,同樣可以形成多數派。Mysql主從同步小夥伴們應該知道mysql的主從架構的資料複製的基本原理
通常一個mysql叢集有一主多從構成。使用者的資料都是寫入主庫Master,Master將資料寫入到本地二進位制日誌binary log中。從庫Slave啟動一個IO執行緒(I/O Thread)從主從同步binlog,寫入到本地的relay log中,同時slave還會啟動一個SQL Thread,讀取本地的relay log,寫入到本地,從而實現資料同步。
資料同步方案根據上面的mysql主從資料複製方案,那我們是不是可以自己寫個元件,也讀取binlog日誌,解析出sql語句;然後同步到另一個mysql叢集呢?
這樣就可以實現了一個叢集的資料,同步到另一個叢集中。
那這個元件需要我們自己寫嗎?這個元件可以參考binlog的協議,只要有資深的網路程式設計知識,是能夠實現的。
當然現在也不需要我們自己編寫,現在市面上有成熟開源的
阿里巴巴開源的canal美團開源的pumalinkedin開源的databus我們可以利用這些開源元件訂閱binlog日誌,解析到變化資料同步到目標庫中。整個過程可以分為2步,第一步訂閱獲得變化的資料,第二步是把變化資料更新到其他目標庫。
這邊所說的目標庫,不單單為mysql叢集,也可以為redis,es等
上圖我們透過訂閱binlog,完成比較有代表性的資料同步
多機房Mysql同步根據上面的知識,多機房的mysql的資料同步,可以也採用binlog方案
北京使用者的資料不斷寫入離自己最近的機房的DB,透過binlog訂閱元件訂閱這個庫binlog,然後下游的更新元件將binlog轉換成SQL,插入到目標庫。上海使用者類似,只不過方向相反,不再贅述。透過這種方式,我們可以實時的將兩個庫的資料同步到對端。
上面的方案面對binlog更新不頻繁的場景,應該問題不大;但是如果更新很頻繁,那麼binlog日誌量會很大,處理更新資料的元件很有可能會頂不住,那如何處理?
最佳化同步方案為了解決binlog量過大,更新資料元件處理不過來,可以在此方案中加入MQ進行削峰,如下圖
同步方案的問題我們看到上面的架構,主要是針對增量資料的同步;但一開始專案上線的時候,全量資料怎麼處理呢?這個一般的處理策略是DBA先dump一份源庫完整的資料快照;目標庫匯入快照即可。
下面我們看看增量資料同步,仔細的小夥伴們應該會看到北京IDC和上海IDC之間的資料是雙向的,因為北京使用者的資料是更新到北京DB的,上海使用者的資料是更新到上海DB的,所以業務上面也是必須是雙向的。
整個資料同步的過程會出現幾個問題:
如何解決重複插入?考慮以下情況下,源庫中的一條記錄沒有唯一索引。對於這個記錄的binlog,透過更新元件將binlog轉換成sql插入目標庫時,丟擲了異常,此時我們並不知道知道是否插入成功了,則需要進行重試。如果之前已經是插入目標庫成功,只是目標庫響應時網路超時(socket timeout)了,導致的異常,這個時候重試插入,就會存在多條記錄,造成資料不一致。
因此,通常,在資料同步時,通常會限制記錄必須有要有主鍵或者唯一索引。
對於DDL語句如何處理?如果資料庫表中已經有大量資料,例如千萬級別、或者上億,這個時候對於這個表的DDL變更,將會變得非常慢,可能會需要幾分鐘甚至更長時間,而DDL操作是會鎖表的,這必然會對業務造成極大的影響。
因此,同步元件通常會對DDL語句進行過濾,不進行同步。DBA在不同的資料庫叢集上,透過一些線上DDL工具進行表結構變更。
如何解決唯一索引衝突?由於兩邊的庫都存在資料插入,如果都使用了同一個唯一索引,那麼在同步到對端時,將會產生唯一索引衝突。對於這種情況,通常建議是使用一個全域性唯一的分散式ID生成器來生成唯一索引,保證不會產生衝突。
另外,如果真的產生衝突了,同步元件應該將衝突的記錄儲存下來,以便之後的問題排查。
如何解決資料迴環問題?此問題是資料同步經常出現的,也是必須需要解決的。最重要的問題。我們針對INSERT、UPDATE、DELETE三個操作來分別進行說明:
INSERT操作假設在A庫插入資料,A庫產生binlog,之後同步到B庫,B庫同樣也會產生binlog。由於是雙向同步,這條記錄,又會被重新同步回A庫。由於A庫本來就存在這條記錄了,產生衝突。
UPDATE操作先考慮針對A庫某條記錄R只有一次更新的情況,將R更新成R1,之後R1這個binlog會被同步到B庫,B庫又將R1同步會A庫。對於這種情況下,A庫將不會產生binlog。因為A庫記錄當前是R1,B庫同步回來的還是R1,意味著值沒有變。
在一個更新操作並沒有改變某條記錄值的情況下,mysql是不會產生binlog,相當於同步終止。下圖演示了當更新的值沒有變時,mysql實際上不會做任何操作:
上圖演示了,資料中原本有一條記錄(1,"tianshouzhi”),之後執行一個update語句,將id=1的記錄的name值再次更新為”tianshouzhi”,意味著值並沒有變更。這個時候,我們看到mysql 返回的影響的記錄函式為0,也就是說,並不會產生的更新操作。
小夥伴們是不是以為,update操作不會有迴環問題了;事實上並不是,我們看一些場景:
考慮A庫的記錄R被連續更新了2次,第一次更新成R1,第二次被更新成R2;這兩條記錄變更資訊都被同步到B庫,B也產生了R1和R2。由於B的資料也在往A同步,B的R1會被先同步到A,而A現在的值是R2,由於值不一樣,將會被更新成R1,併產生新的binlog;此時B的R2再同步會A,發現A的值是R1,又更新成R2,也產生binlog。由於B同步回A的操作,讓A又產生了新的binlog,A又要同步到B,如此反覆,陷入無限迴圈中。
這個後果將會進入死迴圈。
DELETE操作同樣存在先後順序問題。例如先插入一條記錄,再刪除。B在A刪除後,又將插入的資料同步回A,接著再將A的刪除操作也同步回A,每次都會產生binlog,陷入無限迴環。
總結今天老顧介紹了基本的多機房同步mysql的方案,以及同步方案遇到的一些問題,以及一些解決方案;但還遺留了資料迴環問題,老顧將在下一篇文章中介紹解決方案。謝謝!!!
---End---
老顧的微服務閘道器分享課程,請大家多多支援
推薦閱讀
一線大廠級別公共Redis叢集監控,細化到每個專案例項
Sharding-jdbc的實戰入門之水平分表(一)
Sharding-Jdbc之水平分庫和讀寫分離(二)
a、dubbo如何處理業務異常,這個一定要知道哦!
b、企業級SpringBoot應用多個子專案配置檔案規劃、多環境支援(一)
c、企業級SpringBoot應用多個子專案配置檔案規劃、多環境支援(二)
d、企業級SpringBoot應用多個子專案配置檔案之配置中心(三)
e、利用阿里開源工具進行排查線上CPU居高問題
f、阿里二面:如何快速排查死鎖?如何避免死鎖?
g、微服務分散式架構中,如何實現日誌鏈路跟蹤?
h、閘道器如何聚合各個微服務的介面文件?
i、Kubernetes之POD、容器之間的網路通訊
j、K8S中的Service的存在理由
k、企業微服務專案如何進入K8S的全過程
l、阿里開源專案Sentinel限流、降級的統一處理
m、大廠二面:Redis的分散式布隆過濾器是什麼原理?
1、基於RocketMq的SpringCloud Stream框架實戰入門
2、如何搭建訊息中介軟體應用框架之SpringCloud Stream
3、面試必備:閘道器異常了怎麼辦?如何做全域性異常處理?
4、Gateway網關係列(二):SpringCloud Gateway入門實戰,路由規則
5、Gateway網關係列開篇:SpringCloud的官方閘道器Gateway介紹
6、API閘道器在微服務架構中的應用,這一篇就夠了
7、學習Lambda表示式看這篇就夠了,不會讓你失望的哦(續篇)
8、Lambda用在哪裡?幾種場景?
9、為什麼會出現Lambda表示式,你知道嗎?
10、不說“分散式事務”理論,直接上大廠阿里的解決方案,絕對實用
11、女程式設計師問到這個問題,讓我思考了半天,Mysql的“三高”架構
12、大廠二面:CAP原則為什麼只能滿足其中兩項?而不能同時滿足
13、阿里P7二面:聊聊零複製的原理
14、秒殺系統的核心點都在這裡,快來取
15、你瞭解如何利用token方式實現分散式Session嗎?
16、Mysql索引結構演變,為什麼最終會是那個結構呢?讓你一看就懂
17、一場比賽涉及到的知識,用通俗易通的方式介紹併發協調
18、企業實戰Redis全方面思考,你思考了嗎?
19、面試題:Thread的start和run的區別
20、面試題:什麼是CAS?CAS的作用以及缺點
21、如何訪問redis中的海量資料?避免事故產生
22、如何解決Redis熱點問題?以及如何發現熱點?
23、如何設計API介面,實現統一格式返回?
24、你真的知道在生產環境下如何部署tomcat嗎?
25、分享一線網際網路大廠分散式唯一ID設計 之 snowflake方案
26、分享大廠分散式唯一ID設計方案,快來圍觀
27、你想了解一線大廠的分散式唯一ID生成方案嗎?
28、你知道如何處理大資料量嗎?(資料拆分篇)
29、如何永不遷移資料和避免熱點? 根據伺服器指標分配資料量(揭秘篇)
30、你知道怎麼分庫分表嗎?如何做到永不遷移資料和避免熱點嗎?
31、你瞭解大型網站的頁面靜態化嗎?
32、你知道如何更新快取嗎?如何保證快取和資料庫雙寫一致性?
33、你知道怎麼解決DB讀寫分離,導致資料不一致問題嗎?
34、DB讀寫分離情況下,如何解決快取和資料庫不一致性問題?
35、你真的知道怎麼使用快取嗎?
36、如何利用鎖,防止快取擊穿?重構思想的重要性
37、海量訂單產生的業務高峰期,如何避免訊息的重複消費?
38、你知道如何保障生產端100%訊息投遞成功嗎?
39、微服務下的分散式session該如何管理?
40、阿里二面:filter、interceptor、aspect應如何選擇?很多人中招
41、網際網路架構重要組員CDN,很多高階開發都沒有實操過,來看這裡
42、阿里二面:CDN快取控制原理,看看能不能難住你
43、SpringCloud Alibaba之Nacos多環境多專案管理
44、SpringCloud Alibaba系列之Nacos配置中心玩法
45、SpringCloud Alibaba之Nacos註冊中心
46、SpringCloud Plus版本之SpringCloud Alibaba
47、SpringCloud Alibaba之Nacos叢集、持久化
48、SpringCloud Alibaba之Nacos共享配置、灰度配置
49、SpringCloud Alibaba之Sentinel工作原理
50、SpringCloud Alibaba之Sentinel流控管理
51、SpringCloud Alibaba之Sentinel降級管理
52、SpringCloud Alibaba之Sentinel熱點引數限流
53、SpringCloud Alibaba之Sentinel的API實戰