@
概述
定義
Maxwell 官網地址 https://maxwells-daemon.io/
Maxwell GitHub原始碼地址 https://github.com/zendesk/maxwell
Maxwell 是由美國 Zendesk 開源,採用 Java 語言開發的 MySQL 實時抓取工具,透過實時讀取MySQL binlog二進位制日誌並作為生產者生產 JSON 格式訊息傳送給 Kafka、Kinesis、RabbitMQ、Redis或其他流媒體平臺的應用程式。最新版本為1.39.4
Maxwell的操作開銷很低,只需要mysql和資料同步目的地,常用場景包括ETL、快取構建/過期、指標收集、搜尋索引和服務間通訊。
原理
Maxwell 的工作原理很簡單,就是把自己偽裝成 MySQL 的一個 slave,然後以 slave的身份從 MySQL master伺服器複製資料,需要MySQL的binlog資料格式設定為row模式。
Binlog說明
MySQL開啟binlog大概會有 1%的效能損耗,主要用於主從複製和資料恢復。二進位制日誌包括兩類檔案
- 二進位制日誌索引檔案(檔名字尾為.index):用於記錄所有 的二進位制檔案
- 二進位制日誌檔案(檔名字尾為.00000*):記錄資料庫所有的 DDL 和 DML(除了資料查詢語句)語句事件。
MySQL 生成的 binlog 檔案初始大小一定是 154 位元組,然後字首是 log-bin 引數配置的,字尾是預設從.000001,然後依次遞增(包括每次重啟mysql也會遞增)。除了 binlog 檔案檔案以外,MySQL 還會額外生產一個.index 索引檔案用來記錄當前使用的 binlog 檔案。
Maxwell和Canal的區別
Maxwell最初的設計思想是MySQL+Kafka,用於對MySQL資料採集個人比較推薦Maxwell,當然還有我們前面學過的FlinkCDC。
- 服務端+客戶端一體,輕量級
- 支援斷點還原功能+bootstrap+json,全量同步
- maxwell社群比canal社群活躍
部署
安裝
# 下載最新版本1.39.4的maxwell,注意從github的release歷史中可知maxwell從v1.30.0開始就已經不再支援JDK8,支援JDK11
wget https://github.com/zendesk/maxwell/releases/download/v1.39.4/maxwell-1.39.4.tar.gz
# 解壓檔案
tar -xvf maxwell-1.39.4.tar.gz
# 進入主目錄
cd maxwell-1.39.4
MySQL準備
修改mysql的配置檔案,開啟mysql的binlog設定,vim /etc/my.cnf
# mysql server的id,如果有多臺id需要唯一
server_id=1
# 設定生成的二進位制檔案的字首
log-bin=mysql-bin
# 設定binlog的二進位制檔案的日誌級別 行級模式
binlog_format=row
# binlog的執行的庫 如果不加這個引數那麼mysql會對所有的庫都生成對應的binlog 即對所有的庫盡心binlog監控
# 設定只監控某個或某些資料庫
binlog-do-db=my_maxwell_01
binlog-do-db=my_maxwell_02
# 修改後重啟MySQL的服務
service mysqld restart
初始化Maxwell後設資料庫
在 MySQL 中建立一個 maxwell 庫用於儲存 Maxwell 的後設資料
# 建立資料庫,在我們使用的時候它會自己建立對應的表,這裡我們只需建庫不需要創表
CREATE DATABASE maxwell;
# 建立使用者任意遠端訪問
CREATE USER 'maxwell'@'%';
# 修改密碼
ALTER USER 'maxwell'@'%' IDENTIFIED WITH mysql_native_password BY '123456';
#給使用者授權
GRANT SELECT ,REPLICATION SLAVE , REPLICATION CLIENT ON *.* TO maxwell@'%';
GRANT ALL PRIVILEGES ON maxwell.* TO "maxwell"@"%";
#重新整理許可權
FLUSH PRIVILEGES;
Maxwell程式啟動
命令列引數
# 啟動maxwell
bin/maxwell --user='maxwell' --password='123456' --host='hadoop3' --port=3308 --producer=stdout
詳細引數配置可以查閱官網
# 在mysql中建立前面在MySQL的配置檔案中binlog資料庫
CREATE DATABASE my_maxwell_01;
# 資料表,賬號表
use my_maxwell_01;
CREATE TABLE `account` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`age` int(4) DEFAULT 0,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
# 插入資料
INSERT INTO account(name,age) VALUES('張三三',20),('李思',23),('王樂',26);
從日誌可以看出建立資料庫、資料表和資料插入捕獲的binlog由maxwell轉換為json的日誌,向 mysql 的my_maxwell_01庫的account表同時插入 3 條資料,控制檯出現了 3 條 json日誌,說明 maxwell 是以資料行為單位進行日誌的採集的。
透過啟動maxwell後我們也可以maxwell後設資料庫的內容,包含核心幾張表資料。
配置檔案
# 複製maxwell根目錄下config.properties.example
cp config.properties.example config.properties
# 修改config.properties配置檔案
log_level=info
producer=stdout
# mysql login info
host=hadoop3
port=3308
user=maxwell
password=123456
# 透過指定配置檔案啟動maxwell
bin/maxwell --config ./config.properties
# 再次插入資料測試
INSERT INTO account(name,age) VALUES('吳三',25);
# 也可以透過jps檢視maxwell程式com.zendesk.maxwell.Maxwell
jps -l
接下里看下修改資料和刪除資料json資料內容,後續主要就是針對json內容做處理
UPDATE account SET age = 28 WHERE id =4;
UPDATE account SET age = 30 WHERE name ='吳三';
DELETE FROM account WHERE id =4;
json內容分別如下,主要是type型別區分,更新包含old資料的值,ts為秒級時間戳。
# 新增
{
"database": "my_maxwell_01",
"table": "account",
"type": "insert",
"ts": 1671434231,
"xid": 5097,
"commit": true,
"data": {
"id": 4,
"name": "吳三",
"age": 25
}
}
# 更新
{
"database": "my_maxwell_01",
"table": "account",
"type": "update",
"ts": 1671434616,
"xid": 6302,
"commit": true,
"data": {
"id": 4,
"name": "吳三",
"age": 28
},
"old": {
"age": 25
}
}
# 刪除
{
"database": "my_maxwell_01",
"table": "account",
"type": "delete",
"ts": 1671434700,
"xid": 6584,
"commit": true,
"data": {
"id": 4,
"name": "吳三",
"age": 30
}
}
實時監控Mysql輸出Kafka
# 啟動 Maxwell 監控 binlog
bin/maxwell --user='maxwell' --password='123456' --host='hadoop3' --producer=kafka --kafka.bootstrap.servers=kafka1:9092 --kafka_topic=test_topic_1
一旦mysql表有了資料的更新麼mysql底層的binlog檔案肯定會有變化,binlog變化了則maxwell程式就能捕捉到這個變化,將之解析並轉換為json資料寫入到kafka裡面。使用kafka的圖形化工具kafka tool檢視資料,點選test_topic_1檢視,不更新資料這裡的topic是不會被建立的,插入資料後test_topic_1就有相關的訊息資料了
# 繼續插入資料
INSERT INTO account(name,age) VALUES('劉說',27);
# 官方的命令列消費指令碼也可以消費到資料
kafka-console-consumer.sh --bootstrap-server kafka1:9092 --topic test_topic_1
透過 kafka 消費者來檢視到了資料,說明資料成功傳入 kafka
Kafka Topic分割槽控制
上面的示例往kafka寫入的訊息都是是發往一個分割槽,在實際生產環境中一般都會用 maxwell 監控多個 mysql 庫的資料,然後將這些資料發往 kafka 的一個主題 Topic,提高併發度主題肯定是多分割槽的。先建立一個名稱test_topic_2,分割槽為3副本為2的topic。
這次使用配置檔案方式,修改config.properties
# 配置生產者是kafka
producer=kafka
# kafka的server
kafka.bootstrap.servers=kafka1:9092
# 指定topoic
kafka_topic=test_topic_2
#按什麼分割槽 [database, table, primary_key, transaction_id, thread_id, column]
producer_partition_by=database
使用配置檔案的方式啟動maxwell程式
bin/maxwell --config ./config.properties
# 在mysql中建立前面在MySQL的配置檔案中binlog資料庫
CREATE DATABASE my_maxwell_02;
# 資料表,賬號表
use my_maxwell_02;
CREATE TABLE `account` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`age` int(4) DEFAULT 0,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
# 分別往兩個資料庫的account表插入一條資料
INSERT INTO my_maxwell_01.account(name,age) VALUE('李丹',30);
INSERT INTO my_maxwell_02.account(name,age) VALUE('李丹',30);
再來看看topic,在test_topic_2中兩條資料分割槽分別為0和1,驗證不同資料庫的資料會發往不同的分割槽。
實時監控MySQL指定表
主要是透過--filter引數設定exclude排除,include是包含來實現
# 啟動maxwell
bin/maxwell --user='maxwell' --password='123456' --host='hadoop3' --filter 'exclude: *.*, include:my_maxwell_01.product' --port=3308 --producer=stdout
建立新的資料表,分別往兩張表插入資料
use my_maxwell_02;
CREATE TABLE `product` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`type` int(4) DEFAULT 0,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO my_maxwell_01.account(NAME,age) VALUE('李丹',30);
INSERT INTO my_maxwell_01.product(NAME,TYPE) VALUE('iphone13',1);
可以看到只有product表捕獲變更資料,此外還可以設定 include:my_maxwell_01.*,透過此種方式來監控 mysql 某個庫的所有表,也就是說過濾整個庫。
監控MySQL指定表同步全量資料
監控MySQL指定表同步全量資料常用於資料初始化操作,Maxwell 程式預設只能監控 mysql 的 binlog 日誌的新增及變化的資料,但是Maxwell 是支援資料初始化的,可以透過修改 Maxwell 的後設資料,來對 MySQL 的某張表進行資料初始化,也就是我們常說的全量同步
。接下來演示將 my_maxwell_01庫下的 account表的5條資料全量匯入輸出到 maxwell 控制檯。
前面我們建立過maxwel的後設資料庫,這裡需求修改 Maxwell 的後設資料以觸發資料初始化機制,在 mysql 的 maxwell 庫中 bootstrap表中插入一條資料,寫明需要全量資料的庫名和表名
insert into maxwell.bootstrap(database_name,table_name) values('my_maxwell_01','account');
# 啟動 maxwell 程式,此時初始化程式會直接列印account表的所有資料
bin/maxwell --user='maxwell' --password='123456' --host='hadoop3' --port=3308 --producer=stdout
當資料全部初始化完成以後,Maxwell 的後設資料會變化,is_complete 欄位從 0 變為 1,start_at 欄位從 null 變為具體時間(資料同步開始時間),complete_at 欄位從 null 變為具體時間(資料同步結束時間),在Maxwell 執行過程中繼續往maxwell.bootstrap插入資料也會觸發處理。
本人部落格網站IT小神 www.itxiaoshen.com