官方文檔
canal-php
簡介
- canal server偽裝自己為 MySQL slave 萄金,向 MySQL master 發(fā)送 dump 協(xié)議
- 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
前期準(zhǔn)備
我本次測試使用的是phpstudy自帶的mysql8.0.12,需要先開啟 Binlog 寫入功能贝室,配置 binlog-format 為 ROW 模式,my.cnf 中配置如下,phpstudy默認(rèn)配置就是這樣,不用修改
[mysqld]
log-bin=mysql-bin # 開啟 binlog
binlog-format=ROW # 選擇 ROW 模式
server_id=1 # 配置 MySQL replaction 需要定義想虎,不要和 canal 的 slaveId 重復(fù)
授權(quán) canal 鏈接 MySQL 賬號具有作為 MySQL slave 的權(quán)限, 如果已有賬戶可直接 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
//賦予權(quán)限
$ chmod +x run.sh
//構(gòu)建一個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鏡像
讓我們稍微等幾年看看什么情況...
容器跑起來了,默認(rèn)端口是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;
}
-
執(zhí)行canal.php
去數(shù)據(jù)庫改幾條數(shù)據(jù)看看
收到binlog消息
- 實戰(zhàn)成功
什么時候可以使用Canal
mysql和es,redis,mongdb信息同步
可以不用在應(yīng)用層加代碼就可以實現(xiàn)數(shù)據(jù)同步
mysql 不停機舊表遷移新表
1.canal-server開始監(jiān)聽舊表table的binlog,保存到日志文件canal.log(也可以存到mq)
2.mysqldump備份舊表生成table.sql,記錄執(zhí)行mysqldump的大概時間
3.寫代碼按新的規(guī)則導(dǎo)入table.sql到新表table_new
4.寫代碼按新的規(guī)則消費canal.log到新表table_new(取mysqldump之后的log)
5.比較兩個表數(shù)據(jù)是否一致
6.停止消費canal.log
7.原子操作換名
RENAME TABLE `table` TO `table_old`, `table_new` TO `table`
8.寫代碼按新的規(guī)則繼續(xù)消費canal.log到table(如果canal.log還有沒有同步完的操作)
9.刪除table_old
10.評論區(qū)有沒有更好的方式,求留言