Canal實戰(zhàn)

官方文檔

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鏡像


image.png

讓我們稍微等幾年看看什么情況...

image.png

容器跑起來了,默認(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ù)看看


    image.png

收到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ū)有沒有更好的方式,求留言
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容