日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

erosa mysql_MySQL协议和canal实现

發布時間:2023/12/3 数据库 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 erosa mysql_MySQL协议和canal实现 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言

前面的文章里,我們了解到 canal 可以從 MySQL 中感知數據的變化。這是因為它模擬 MySQL slave 的交互協議,偽裝自己為 MySQL slave ,從而實現了主從復制。

正是了解到這一點,筆者有兩個問題便一直縈繞于心:它是如何模擬 MySQL slave 交互協議的?

它又是怎么解析 binlog 日志的呢?

今天,筆者準備就著這兩個問題,扒拉扒拉 canal 的代碼,一探究竟。

一、MySQL 主從復制

在談 canal 之前,我們有必要再重溫下 MySQL 主從復制的原理。

總結上圖的流程如下:MySQL master 將數據變更寫入二進制日志 (binary log , 其中記錄叫做二進制日志事件binary log events);

MySQL slave 將 master 的 binary log events 拷貝到它的中繼日志 (relay log);

MySQL slave 重放 relay log 中的事件,將數據變更反映到自己的數據庫。

二、canal 原理

上圖就很形象的描述了 canal 的角色。它的原理也很簡單:canal模擬mysql slave的交互協議,偽裝自己為mysql slave,向mysql master發送dump協議;

mysql master收到dump請求,開始推送binary log給slave(也就是canal);

canal解析binary log對象(原始為byte流);

canal將解析后的對象,根據業務場景,分發到比如 MySQL 、RocketMQ 或者 ES 中。

三、源碼啟動

看完了 MySQL 主從復制和 canal 原理之后,為了方便 debug ,筆者已經在 GitHub Fork 了源碼,并導入本地。

可以找到?com.alibaba.otter.canal.deployer.CanalLauncher?類,它就是 canal 獨立版本啟動的入口類。

在這里,直接運行 main 方法即可運行 canal ,和在?/canal/bin/startup.sh?中效果一樣。

事實上,canal 的代碼比較多,在架構上又分了很多模塊設計,比如事件解析器、事件消費、內存存儲、服務實例、元數據、高可用等。

本文不打算面面俱到介紹每一個的實現,那就得正兒八經寫一個 canal 系列才行。主要還是為了開頭我們提出的那兩個問題。

四、如何模擬slave ?

上面我們已經說到,?CanalLauncher是canal 啟動的入口類。

運行 main 方法之后, canal 會先做很多準備工作。比如加載配置文件、初始化消息隊列、啟動 canal Admin、加載Spring配置、注冊鉤子程序等。

canal 模擬 slave 協議,是在?EventParser模塊中開始進行的。

在 canal 代碼中,整個流程簡化如下://?開始執行replication//?1.?構造Erosa連接ErosaConnection?erosaConnection?=?buildErosaConnection();//?2.?啟動一個心跳線程startHeartBeat(erosaConnection);//?3.?執行dump前的準備工作preDump(erosaConnection);erosaConnection.connect();//?鏈接//?查詢master?serverIdlong?queryServerId?=?erosaConnection.queryServerId();if?(queryServerId?!=?0)?{????serverId?=?queryServerId;}//?4.?獲取binlog最后的位置信息EntryPosition?position?=?findStartPosition(erosaConnection);final?EntryPosition?startPosition?=?position;//?加載元數據processTableMeta(startPosition);//?重新鏈接,因為在找position過程中可能有狀態,需要斷開后重建erosaConnection.reconnect();//?4.?開始dump數據erosaConnection.dump(startPosition.getJournalName(),startPosition.getPosition(),sinkHandler);

1、握手、驗證

在開始之前,canal 必須先要和 MySQL 服務器建立連接,并完成客戶端身份驗證。

在 MySQL 中,連接過程協議如下:

在代碼中,我們看一下它的連接方法:

其中,?negotiate方法是握手協議和客戶端驗證的具體實現。就是按照 MySQL 的協議規范,通過上面創建的?Socketchannel來讀寫網絡數據。

2、dump前的準備

正確連接到 MySQL 后,在開始執行 dump 指令之前,還要初始化一些配置信息。

思路就是通過 MySQL 執行器,執行 SQL 語句,獲取信息。

代碼就不粘了,不過它們執行的語句如下:show?variables?like?'binlog_format'??????#獲取binlog?format格式show?variables?like?'binlog_row_image'???#獲取binlog?image格式show?variables?like?'server_id'??????????#獲取matser?serverIdshow?master?status???????????????????????#獲取binlog名稱和position

3、注冊slave

現在開始調用?erosaConnection.dump(binlogfilename,binlogPosition,func)方法,來注冊slave和發送dump命令。

在使用?COM_BINLOG_DUMP請求binlog事件之前發送,在主服務器上注冊一個從服務器,它的指令是?COM_REGISTER_SLAVE。

注冊完之后,就是發送dump請求,它的指令是?COM_BINLOG_DUMP。

在執行完這段代碼后,我們通過?show processlist;查看進程,就可以看到這個dump線程的狀態。

其中 command =?Binlog Dump

state = Master has sent all binlog to slave; waiting for more updates。

五、如何解析binlog數據 ?

在上面章節中,我們已經看到,MySQL主服務器已經接受了 canal 這個從服務器,那么當canal拿到binlog內容后, 又是怎么解析它的呢?

首先,還記得在配置MySQL服務器的時候,我們將?binlog-format設置為ROW模式,它是基于行的復制。

binlog中每一個數據變更可以叫做事件,在ROW模式下,有幾個主要的事件類型:事件SQL命令rows 內容TABLEMAPEVENTnull定義將要更改的表。

WRITEROWSEVENT插入要插入的行數據

DELETEROWSEVENT刪除被刪除的數據

UPDATEROWSEVENT更新原數據+要更改的數據

每一次數據的變更,都會觸發2個事件,先把要更改的表信息告訴你,然后再告訴你更改的row內容。

比如?TABLE_MAP_EVENT+WRITE_ROWS_EVENT。

canal在接收到binlog數據后,并不會馬上把它解析成我們熟悉的JSON數據,而是在發送的時候才開始。

比如我們選擇使用?RocketMQ,那么在發送之前才開始將binlog里面的byte數組轉化為對象。//?并發構造EntryRowData[]?datas?=?MQMessageUtils.buildMessageData(message,?executor);//?串行分區List?flatMessages?=?MQMessageUtils.messageConverter(datas,?message.getId());

在這兩個方法里,就完成了byte數組到對象的轉化。轉化成的?FlatMessage對象,就成了我們在消息隊列中消費到的數據結構。public?class?FlatMessage?implements?Serializable?{????private?long??????????????????????id;????private?String????????????????????database;????private?String????????????????????table;????private?List??????????????pkNames;????private?Boolean???????????????????isDdl;????private?String????????????????????type;????//?binlog?executeTime????private?Long??????????????????????es;????//?dml?build?timeStamp????private?Long??????????????????????ts;????private?String????????????????????sql;????private?Map??????sqlType;????private?Map???????mysqlType;????private?List>?data;????private?List>?old;}

總結

正如本文開頭所言,筆者在剛了解到canal機制的時候,確實覺得很不可思議。

咦,它是怎么模擬MySQL slave的呢 ?總覺得是不是有啥黑科技在里面。。。

事實上,這是源于筆者對MySQL的無知。

MySQL早就制定好了各種接口協議,怎么連接、驗證、注冊和dump都明明白白的寫在那兒啦。

總結

以上是生活随笔為你收集整理的erosa mysql_MySQL协议和canal实现的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。