官方文件
canal-php
簡介
- canal server偽裝自己為 MySQL slave ,向 MySQL master 傳送 dump 協議
- MySQL master 收到 dump 請求,開始推送 binary log 給canal server
- canal server 解析 binary log 物件(原始為 byte 流)
- canal client連線上canal server之後可以實時收到MySQL master推送過來的binlog
- canal server也可以把binlog直接推送到MySQL,Hbase,Es,Mongodb,Redis,RabbitMq,RocketMq
前期準備
我本次測試使用的是phpstudy自帶的mysql8.0.12,需要先開啟 Binlog 寫入功能,配置 binlog-format 為 ROW 模式,my.cnf 中配置如下,phpstudy預設配置就是這樣,不用修改
[mysqld]
log-bin=mysql-bin # 開啟 binlog
binlog-format=ROW # 選擇 ROW 模式
server_id=1 # 配置 MySQL replaction 需要定義,不要和 canal 的 slaveId 重複
授權 canal 連結 MySQL 賬號具有作為 MySQL slave 的許可權, 如果已有賬戶可直接 grant
CREATE USER canal IDENTIFIED BY 'canal';
GRANT SELECT, REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'canal'@'%';
-- GRANT ALL PRIVILEGES ON *.* TO 'canal'@'%' ;
FLUSH PRIVILEGES;
安裝Canal Server
我這裡選擇用docker安裝
//下載指令碼
# wget https://raw.githubusercontent.com/alibaba/canal/master/docker/run.sh
//賦予許可權
# chmod +x run.sh
//構建一個destination name為test的佇列
./run.sh
-e canal.auto.scan=false
-e canal.destinations=test
-e canal.instance.master.address=127.0.0.1:3306
-e canal.instance.dbUsername=canal
-e canal.instance.dbPassword=canal
-e canal.instance.connectionCharset=UTF-8
-e canal.instance.tsdb.enable=true
-e canal.instance.gtidon=false
指令碼會docker pull最新的canal/canal-server映象
讓我們稍微等幾年看看什麼情況…
容器跑起來了,預設埠是11111,destinations是test
啟動Canal-client
獲取canal-client
composer require xingwenge/canal_php
新建canal.php
<?php namespace xingwenge\canal_php\sample; use xingwenge\canal_php\CanalClient; use xingwenge\canal_php\CanalConnectorFactory; use xingwenge\canal_php\Fmt; require_once './vendor/autoload.php'; ini_set('display_errors', 'On'); error_reporting(E_ALL); try { $client = CanalConnectorFactory::createClient(CanalClient::TYPE_SOCKET_CLUE); # $client = CanalConnectorFactory::createClient(CanalClient::TYPE_SWOOLE); $client->connect("127.0.0.1", 11111); $client->checkValid(); $client->subscribe("1001", "test", ".*\\..*"); # $client->subscribe("1001", "test", "db_name.tb_name"); # 指定某個庫某個表 while (true) { $message = $client->get(100); if ($entries = $message->getEntries()) { foreach ($entries as $entry) { Fmt::println($entry); } } sleep(1); } $client->disConnect(); } catch (\Exception $e) { echo $e->getMessage(), PHP_EOL; }
執行canal.php
去資料庫改幾條資料看看
收到binlog訊息實戰成功
什麼時候可以使用Canal
mysql和es,redis,mongdb資訊同步
可以不用在應用層加程式碼就可以實現資料同步
mysql 不停機舊錶遷移新表
1.canal-server開始監聽舊錶table的binlog,儲存到日誌檔案canal.log(也可以存到mq)
2.mysqldump備份舊錶生成table.sql,記錄執行mysqldump的大概時間
3.寫程式碼按新的規則匯入table.sql到新表table_new
4.寫程式碼按新的規則消費canal.log到新表table_new(取mysqldump之後的log)
5.比較兩個表資料是否一致
6.停止消費canal.log
7.原子操作換名
RENAME TABLE `table` TO `table_old`, `table_new` TO `table`
8.寫程式碼按新的規則繼續消費canal.log到table(如果canal.log還有沒有同步完的操作)
9.刪除table_old
10.評論區有沒有更好的方式,求留言
本作品採用《CC 協議》,轉載必須註明作者和本文連結