首頁>技術>

前言

在前一篇文章中,老顧介紹了如何基於binlog實現多機房mysql同步的方案;在這篇文章最後遺留了迴環問題,今天這篇文章我們就來看看如何解決迴環的問題

問題本質

所有產生的迴環問題,就是北京DB產生了binlog;更新到了上海DB,上海DB又產生了binlog,北京的訂閱服務又訂閱到了此binlog;但此時由上海DB產生的binlog應該要過濾掉,而不是執行。

問題的本質只要我們能夠過濾掉迴環過來的binlog 或者 即使執行了迴環過來的binlog也不會產生資料的更新即可。

我們先來看看,現在大家都用了哪些方案去解決此類問題。

往目標庫插入不生成binlog

此方案的想法是就是讓上海DB不產生binlog;設定引數set sql_log_bin=0,這樣就不會產生binlog。

我們先看一下當前的binlog;

show binlog events

插入一條語句,再次檢視binlog;的確沒有產生新的binlog事件

透過這種方式,貌似可以解決資料迴環問題。目標庫不產生binlog,就不會被北京訂閱元件同步到binlog。

但是這種方案是不可行的,因為我們上海的DB也是叢集部署,如:一主多從;如果我們往master節點插入資料,如果不產生binlog,那麼slave節點也無法同步資料。這個不是我們想要的。

控制binlog同步方向

既然不產生binlog不能解決問題。那我們控制迴環過來binlog不執行,插入某個庫之前,我們先判斷這條記錄是不是原本就是這個庫產生的,如果是,那麼就拋棄,也可以避免迴環問題。

ROW模式下記錄sql

mysql主從同步,binlog複製一般有3種模式。STATEMENT,ROW,MIXED。預設情況下,STATEMENT模式只記錄SQL語句,ROW模式只記錄欄位變更前後的值,MIXED模式是二者混合。 binlog同步一般使用的都是ROW模式,高版本Mysql主從同步預設也是ROW模式

/*IDC1:DB1*/insert into users(name) values("gujiachun")

其中/*IDC1:DB1*/是一個註釋,表示這個SQL原始在是IDC1的DB1中產生的。之後,在同步的時候,解析出SQL中的IDC資訊,就能判斷出是不是自己產生的資料。

然而,ROW模式下,預設只記錄變更前後的值,不記錄SQL。所以,我們要透過一個開關,讓Mysql在ROW模式下也記錄INSERT、UPDATE、DELETE的SQL語句。具體做法是,在mysql的配置檔案中,新增以下配置:

binlog_rows_query_log_events =1

這個配置可以讓mysql在binlog中產生ROWS_QUERY_LOG_EVENT型別的binlog事件,其記錄的就是執行的SQL

透過這種方式,我們就記錄下的一個binlog最初是由哪一個叢集產生的,之後在同步的時候判斷目標機房和當前binlog中包含的機房相同,則拋棄這條資料,從而避免迴環。

如果採用這種方案,可以考慮在資料庫訪問層中介軟體層面新增支援在sql之前增加/*..*/的功能,統一對業務遮蔽。即使這樣,也不完美,不能保證所有的sql都透過中介軟體來來寫入,例如DBA的一些日常運維操作,或者手工透過mysql命令列來操作資料庫時,肯定會存在沒有新增機房資訊的情況。

總的來說,這個方案沒有落地行。

透過附加表記錄binlog產生源叢集資訊

這種方案目前很多公司使用。大致思路是,在db中都加一張額外的表,例如叫direction,記錄一個binlog產生的源叢集的資訊。例如

CREATE TABLE `direction` (  `idc` varchar(255) not null,  `db_cluster` varchar(255) not null,) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4

idc欄位用於記錄某條記錄原始產生的IDC,db_cluster用於記錄原始產生的資料庫叢集(注意這裡要使用叢集的名稱,不能是server_id,因為可能會發生主從切換)。

假設使用者在IDC1的庫A插入的一條記錄(也可以在事務中插入多條記錄,單條記錄,即使不開啟事務,mysql預設也會開啟事務):

BEGIN;insert into users(name) values("gujiachun”);COMMIT;

那麼A庫資料binlog透過更新資料同步到目標庫B時,可以提前對事務中的資訊可以進行一些修改,,如下所示:

BEGIN;#往目標庫同步時,首先額外插入一條記錄,表示這個事務中的資料都是A產生的。insert into direction(idc,db_cluster) values("IDC1”,"DB_A”)#插入原來的記錄資訊insert into users(name) values("tianshouzhi”);COMMIT;

之後B庫的資料往A同步時,就可以根據binlog中的第一條記錄的資訊,判斷這個記錄原本就是A產生的進行拋棄,透過這種方式來避免迴環。這種方案已經已經過很多的公司的實際驗證。

透過GTID

Mysql 5.6引入了GTID(全域性事務id)的概念,極大的簡化的DBA的運維。在資料同步的場景下,GTID依然也可以發揮極大的威力。

GTID 由2個部分組成:

server_uuid:transaction_id

其中server_uuid是mysql隨機生成的,全域性唯一。transaction_id事務id,預設情況下每次插入一個事務,transaction_id自增1。我們看看如何避免迴環、資料重複插入的問題

GTID提供了一個會話級變數gtid_next,指示如何產生下一個GTID。可能的取值如下:

AUTOMATIC: 自動生成下一個GTID,實現上是分配一個當前例項上尚未執行過的序號最小的GTID。ANONYMOUS: 設定後執行事務不會產生GTID,顯式指定的GTID。

預設情況下,是AUTOMATIC,也就是自動生成的,例如我們執行sql:

insert into users(name) values("tianbowen”);

產生的binlog資訊如下:

可以看到,GTID會在每個事務(Query->...->Xid)之前,設定這個事務下一次要使用到的GTID。

從源庫訂閱binlog的時候,由於這個GTID也可以被解析到,之後在往目標庫同步資料的時候,我們可以顯示的的指定這個GTID,不讓目標自動生成。也就是說,往目標庫,同步資料時,變成了2條SQL:

SET GTID_NEXT= '09530823-4f7d-11e9-b569-00163e121964:1’insert into users(name) values("tianbowen")

由於我們顯示指定了GTID,目標庫就會使用這個GTID當做當前事務ID,不會自動生成。同樣,這個操作也會在目標庫產生binlog資訊,需要同步回源庫。往源庫同步時,我們按照相同的方式,先設定GTID,在執行解析binlog後得到的SQL,還是上面的內容

SET GTID_NEXT= '09530823-4f7d-11e9-b569-00163e121964:1'insert into users(name) values("tianbowen")

由於這個GTID在源庫中已經存在了,插入記錄將會被忽略,演示如下:

注意這裡,對於一條insert語句,其影響的記錄函式居然為0,也就會插入並沒有產生記錄,也就不會產生binlog,避免了迴圈問題

如何做到的呢?mysql會記錄自己執行過的所有GTID,當判斷一個GTID已經執行過,就會忽略。透過如下sql檢視:

上述value部分,冒號":"前面的是server_uuid,冒號後面的1-5,是一個範圍,表示已經執行過1,2,3,4,5這個幾個transaction_id。這裡就能解釋了,在GTID模式的情況下,為什麼前面的插入語句影響的記錄函式為0了。

顯然,GTID除了可以幫助我們避免資料迴環問題,還可以幫助我們解決資料重複插入的問題,對於一條沒有主鍵或者唯一索引的記錄,即使重複插入也沒有,只要GTID已經執行過,之後的重複插入都會忽略。

當然,我們還可以做得更加細緻,不需要每次都往目標庫設定GTID_NEXT,這畢竟是一次網路通訊。在往目標庫插入資料之前,先判斷目標庫的server_uuid是不是和當前binlog事務資訊攜帶的server_uuid相同,如果相同,則可以直接丟棄。檢視目標庫的gtid,可以透過以下sql執行:

GTID應該算是一個終極的資料迴環解決方案,mysql原生自帶,比新增一個輔助表的方式更輕量,開銷也更低。需要注意的是,這倒並不是一定說GTID的方案就比輔助表好,因為輔助表可以新增機房等額外資訊。在一些場景下,如果下游需要知道這條記錄原始產生的機房,還是需要使用輔助表。

總結

講到這裡關於多機房同步mysql資料的方案已經介紹完整;當然具體用哪些開源元件在這些方面做的比較好。建議的首選,是canal/otter組合。

canal的作用就是類似於前面所述的binlog訂閱元件,拉取解析binlogotter是canal的客戶端,專門用於進行資料同步,類似於前文所講解的更新資料元件。並且,canal的最新版本已經實現了GTID。

當然現在最新的canal客戶端,提供了client.adapter同步元件,只要簡單的配置,就能達到資料同步。小夥伴們可以自行嘗試。以後老顧也會介紹canal的實戰。謝謝!!!

---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面試必備:閘道器異常了怎麼辦?如何做全域性異常處理?

4Gateway網關係列(二):SpringCloud Gateway入門實戰,路由規則

5Gateway網關係列開篇:SpringCloud的官方閘道器Gateway介紹

6API閘道器在微服務架構中的應用,這一篇就夠了

7學習Lambda表示式看這篇就夠了,不會讓你失望的哦(續篇)

8Lambda用在哪裡?幾種場景?

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實戰

11
最新評論
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • 學習tomcat——如何建立連線,處理請求