目录
七、linux设置canal_deployer和canal_adapter服务常驻内存,每次随主机启动而启动(可选)
本文针对canal同步mysql数据库,通过一个测试表来演示同步的安装、配置、示例。
一、下载安装包
wget https://github.com/alibaba/canal/releases/download/canal-1.1.8/canal.adapter-1.1.8.tar.gz
wget https://github.com/alibaba/canal/releases/download/canal-1.1.8/canal.deployer-1.1.8.tar.gz
如果下载很慢,可以百度其他镜像站下载或通过代理方式来下载。
下载完成后,如下图,其中canal_admin提供的一个可视化管理平台,用于集中管理和配置 Canal Deployer、Adapter 实例和同步任务。本文为单机同步,咱不安装它,有兴趣伙伴可以自行尝试。
canal-master.zip是我下载的源码,暂时用不上,忽略它。

二、解压
创建安装目录
mkdir -p /usr/local/canal/canal_deployer && mkdir -p /usr/local/canal/canal_adapter
解压文件到安装目录
tar -zxvf /usr/local/soft/canal.deployer-1.1.8.tar.gz -C /usr/local/canal/canal_deployer
tar -zxvf /usr/local/soft/canal.adapter-1.1.8.tar.gz -C /usr/local/canal/canal_adapter

三、配置canal_deplayer
进入conf目录
cd /usr/local/canal/canal_deployer/conf
修改canal.properties
1.新增这两行
canal.id=1
canal.ip=192.168.7.47 (canal服务所在主机外网IP)
2.修改如下字段值:
canal.register.ip = 你的主机ip,如:192.168.7.47
canal.destinations = example 默认example,此处默认即可
3.进入conf/example目录里,修改instance.properties
cd /usr/local/canal/canal_deployer/conf/example
修改如下字段属性值:
canal.instance.master.address=192.168.7.47:3306 此处为源库ip:端口
canal.instance.dbUsername=root 此处为源库登录账号
canal.instance.dbPassword=root 此处为源库登录密码
canal.instance.filter.regex=test\\.user 指定要同步的库表,例如我要同步test库下的user表canal.instance.filter.regex=test1\\..*|test2\\..*|test3\\..*表示我要同步test1、test2、test3库里的所有表。
新增这两行(可选)
canal.instance.defaultDatabaseName=test 默认同步的数据库名
canal.instance.defaultTableName=user 默认同步的数据库表名4.启动canal_deployer
进入bin目录,执行启动脚本
cd /usr/local/canal/canal_deployer/bin
./startup.sh
5.查看启动日志和执行日志
tail -f /usr/local/canal/canal_deployer/logs/canal/canal.log
tail -f /usr/local/canal/canal_deployer/logs/example/example.log
上图表示canal-deployer启动成功
四、配置canal_adapter
配置canal_adapter之前,一定要将源库test库里的test表结构,导入到目标库test库里,因为Canal Adapter 不会自动建库建表,你需要手动在目标库中建库建表,这步骤千万不要忘记,否则后续日志报找不到字段的异常。

接下来开始配置canal_adapter
1.进入conf目录,修改application.yml
cd /usr/local/canal/canal_adapter/conf
修改内容如下:
canal.tcp.server.host: 192.168.7.47:11111 此处为主机IP:11111,端口尽量不要修改,保持11111即可
#源库登录信息(root之外其他拥有权限的账号也行):
srcDataSources:
defaultDS:
url: jdbc:mysql://192.168.7.47:3306/test?useUnicode=true
username: root
password: root
#目标库登录信息(root之外其他拥有权限的账号也行):
canalAdapters:
- instance: example # canal instance Name or mq topic name
groups:
- groupId: g1
outerAdapters:
- name: logger
- name: rdb
key: mysql1
properties:
jdbc.driverClassName: com.mysql.jdbc.Driver
jdbc.url: jdbc:mysql://192.168.7.47:4306/test?useUnicode=true
jdbc.username: root
jdbc.password: root
druid.stat.enable: false
druid.stat.slowSqlMillis: 1000
也可以配置多个数据库,如图:defaultDS,defaultDS2,defaultDS3,多个目标库mysql1/mysq2/mysql3
2.进入rdb目录,创建库表同步的配置文件
cd /usr/local/canal/canal_adapter/conf/rdb
例如我要同步test库下的user表,我创建的文件名就是:test_user.yml
内容如下:
dataSourceKey: defaultDS
destination: example
groupId: g1
outerAdapterKey: mysql1
concurrent: true
dbMapping:
database: test
table: user
targetTable: user
targetPk:
id: id
mapAll: true
# targetColumns:
# id:
# name:
# role_id:
# c_time:
# test1:
3.启动canal_adapter
进入bin目录,执行启动脚本
cd /usr/local/canal/canal_adapter/bin && ./startup.sh
4.查看执行日志
tail -f /usr/local/canal/canal_adapter/logs/adapter/adapter.log
如果表示canal_adapter启动成功。
五、测试同步效果
当源库user表插入数据后,刷新目标库,数据已经同步过来了

修改数据的时候也同步过来了

删除李四这条数据后,数据依然同步

至此canal同步单表配置完成
六、拓展(可选)
如果想同步指定库里所有的表,由于表比较多的情况下,canaladapter的rdb目录下要写多个.yml映射文件,太过于繁琐,且效率很低,为此,我们可以写一个脚本,来按每个表生成对应的yml文件
配置前一定要求将源库结构和目标库表结构进行同步,确保两变库表结构一致,这是前提
我这里提供两个脚本:
- start_canal_mysql.sh:负责读取该脚本同级目录里mysql_tables目录里的test1.txt,例如:./mysql_tables/test1.txt,test1.txt文件名为你本次要同步的数据库名,因为我要同步test1库里所有的表,所以我命名为test1.txt,test1.txt里的内容,每行的内容格式:表名|主键字段名
,如果某个表没设置主键,则显示:表名|无,查询指定库下所有表名和主键id字段的sql如下: SELECT CONCAT(t.TABLE_NAME,'|',IFNULL( GROUP_CONCAT(k.COLUMN_NAME ORDER BY k.ORDINAL_POSITION SEPARATOR ', '), '无' ) ) as TABLE_NAME FROM information_schema.TABLES t LEFT JOIN information_schema.KEY_COLUMN_USAGE k ON t.TABLE_SCHEMA = k.CONSTRAINT_SCHEMA AND t.TABLE_NAME = k.TABLE_NAME AND k.CONSTRAINT_NAME = 'PRIMARY' WHERE t.TABLE_SCHEMA = 'test1' GROUP BY t.TABLE_NAME ORDER BY t.TABLE_NAME;
start_canal_mysql.sh脚本内容如下:
canal_mysql.sh#!/bin/bash # 检查参数是否正确 if [ $# -ne 3 ]; then echo "Usage: $0 <database_name> <outer_adapter_key> <data_source_key>" exit 1 fi # 获取脚本所在目录 SCRIPT_DIR=$(cd $(dirname $0); pwd) DB_NAME=$1 # 定义 canal_mysql_table.txt 文件路径 TABLE_LIST_FILE="$SCRIPT_DIR/mysql_tables/$DB_NAME.txt" # 检查文件是否存在 if [ ! -f "$TABLE_LIST_FILE" ]; then echo "Error: File $TABLE_LIST_FILE does not exist." exit 1 fi # 读取数据库名、outer_adapter_key、data_source_key #DB_NAME=$1 OUTER_ADAPTER_KEY=$2 DATA_SOURCE_KEY=$3 # 逐行读取表信息并处理 while IFS='|' read -r TABLE_NAME PK_ID; do # 去除前后空格(如果有的话) TABLE_NAME=$(echo $TABLE_NAME | xargs) PK_ID=$(echo $PK_ID | xargs) # 执行 canal_mysql.sh 脚本 "$SCRIPT_DIR/canal_mysql.sh" "$DB_NAME" "$TABLE_NAME" "$PK_ID" "$OUTER_ADAPTER_KEY" "$DATA_SOURCE_KEY" done < "$TABLE_LIST_FILE" #chmod +x start_canal_mysql.sh #./start_canal_mysql.sh your_database outer_adapter_key data_source_key#!/bin/bash # 检查参数数量是否正确,必须提供4个参数 if [ "$#" -lt 4 ] || [ "$#" -gt 5 ]; then echo "Usage: $0 <database_name> <table_name> <target_pk_id> <outer_adapter_key> [data_source_key]" exit 1 fi # 获取脚本参数 db_name="$1" table_name="$2" target_pk_id="$3" outer_adapter_key="$4" data_source_key="${5:-defaultDS}" # 参数非空校验 if [ -z "${db_name}" ]; then echo "Error: 第一个参数(database_name)不能为空" exit 1 fi if [ -z "${table_name}" ]; then echo "Error: 第二个参数(table_name)不能为空" exit 1 fi if [ -z "${target_pk_id}" ]; then echo "Error: 第三个参数(target_pk_id)不能为空" exit 1 fi if [ -z "${outer_adapter_key}" ]; then echo "Error: 第四个参数(outer_adapter_key)不能为空" exit 1 fi # 定义文件路径和名称 output_dir="/usr/local/canal/canal_adapter/conf/rdb" file_name="${db_name}_${table_name}.yml" output_file="${output_dir}/${file_name}" # 创建目标目录(如果不存在) mkdir -p "$output_dir" rm -rf "$output_file" # 写入内容到YAML文件 cat <<EOF > "$output_file" dataSourceKey: ${data_source_key} destination: example groupId: g1 outerAdapterKey: ${outer_adapter_key} concurrent: true dbMapping: database: ${db_name} table: ${table_name} targetTable: ${table_name} EOF # 判断 target_pk_id 是否为 "无" if [ "${target_pk_id}" != "无" ]; then cat <<EOF >> "$output_file" targetPk: id: ${target_pk_id} EOF else cat <<EOF >> "$output_file" #targetPk: # id: ${target_pk_id} EOF fi cat <<EOF >> "$output_file" mapAll: true etlCondition: "where 1=1" commitBatch: 3000 EOF echo "YAML file created successfully at: $output_file" #chmod +x canal_mysql.sh #./canal_mysql.sh dbName tableName pkId outer_adapter_key data_source_key
脚本执行逻辑:执行start_canal_mysql.sh后,它内部逻辑会自动调取start_canal_mysql.sh,从而最终生成各个表的.yml映射文件
脚本执行:先授权脚本执行权限
chmod +x start_canal_mysql.sh
chmod +x canal_mysql.sh
再执行命令
./start_canal_mysql.sh your_database outer_adapter_key data_source_key
参数:your_database数据库名,例如:test1
outer_adapter_key目标数据库key,可在adapter的application.yml中找到,例如:mysq1
data_source_key源库数据库key,可在adapter的application.yml中找到,例如:defaultDS
执行示例:./start_canal_mysql.sh test1 mysql1 defaultDS
执行结果:

七、linux设置canal_deployer和canal_adapter服务常驻内存,每次随主机启动而启动(可选)
进入cd /etc/systemd/system目录后,创建my_canal_adapter.service和my_canal_deployer.service

my_canal_deployer.service
[Unit]
Description=My Custom Canal deployer Service
[Service]
Type=forking
ExecStart=/usr/local/canal/canal_deployer/bin/restart.sh
WorkingDirectory=/usr/local/canal/canal_deployer/bin
Restart=on-failure
User=root
[Install]
WantedBy=multi-user.target
my_canal_adapter.service
[Unit]
Description=My Custom Canal adapter Service
[Service]
Type=forking
ExecStart=/usr/local/canal/canal_adapter/bin/restart.sh
WorkingDirectory=/usr/local/canal/canal_adapter/bin
Restart=on-failure
User=root
[Install]
WantedBy=multi-user.target
创建完成文件后,启用并启动服务
sudo systemctl daemon-reload
sudo systemctl enable my_canal_deployer.service --now
sudo systemctl enable my_canal_adapter.service --now
查看服务运行状态:














1040

被折叠的 条评论
为什么被折叠?



