简介
以下关于Canal 的介绍来自Github官方介绍。 canal [k?'n?l] ,译意为水道/管道/沟渠,主要用途是基于MySQL 数据库增量日志解析,提供增量数据订阅和消费。
工作原理
canal 模拟MySQL slave 的交互协议,将自己伪装为MySQL slave ,向MySQL master 发送dump 协议。MySQL master 收到dump 请求,开始推送binary log 给slave (即canal )。canal 解析binary log 对象(原始为byte 流)。
因此可以使用Canal 来提供MySQL 数据库增量数据的订阅和消费,当MySQL 数据库中的数据发生变化时,Canal 可以高效地将这些数据同步到下游服务,比如更新Redis 中的数据、提供数据给ElasticSearch 以及更新索引异构表等。
架构
说明:
server 代表一个canal 运行实例,对应于一个jvm 。instance 对应于一个数据队列 (1 个server 对应1-n 个instance )。
instance 模块:
eventParser (数据源接入,模拟slave 协议和master 进行交互,协议解析)。eventSink (Parser 和Store 的链接器,进行数据过滤、加工以及分发的工作)。eventStore (数据存储)。metaManager (增量订阅和消费信息管理器)。
环境准备
本篇博客将介绍如何部署Canal 以及Canal Admin ,而它们的依赖环境必须要提取准备好。
- 安装
Mysql :需要先安装Mysql ,博主这里安装Mysql 8 (Mysql 8 - CentOS yum & Docker安装Mysql 8),使用CentOS yum 方式安装即可,其他操作系统的安装步骤可自行百度。 设置开机自启动并且立即启动Mysql :systemctl enable mysqld & systemctl start mysqld ,查询Mysql 状态:systemctl status mysqld ,状态为active (running) 即可。 - 安装
JDK :还需要配置JDK 环境(JDK8下载地址),下载好压缩包后,使用Xftp 将该压缩包上传到虚拟机中。 解压文件(tar -zxvf jdk-8u202-linux-x64.tar.gz )以及修改/etc/profile 配置文件(vim /etc/profile ,没有vim 可以执行yum install -y vim 进行安装)。这些常用工具的配置还是要自己去理解以及多练习,敲熟了,比搜索加Copy 快多了(export JAVA_HOME=/usr/local/jdk1.8.0_202 、export CLASSPATH=.:$JAVA_HOME/lib 、export PATH=$JAVA_HOME/bin:$PATH )。 使对/etc/profile 配置文件的修改生效(source /etc/profile )。
进入Mysql 创建Canal 和Canal Admin 需要使用的用户,并且授予该用户权限。
create user kaven identified by 'kaven';
授予用户权限(为了方便,博主这里直接授予用户所有权限,可以根据目前的业务需求来设置):
grant all privileges on *.* to 'kaven'@'%';
flush privileges;
还需要修改Mysql 的配置(vim /etc/my.cnf ),要先开启binlog 写入功能,配置binlog-format 为ROW 模式,my.cnf 需要增加的配置如下所示:
[mysqld]
log-bin=mysql-bin
binlog-format=ROW
server_id=1
重启Mysql :
systemctl restart mysqld
部署Canal
博主这里选择1.1.5 版本(Canal Admin 要求Canal 版本>=1.1.4 ,需要依赖canal-server 提供面向admin 的动态运维管理接口),下载下图所示的两个压缩包。 下载好后再将它们上传到虚拟机中。Canal 对应于canal.deployer 项目,Canal Admin 对应于canal.admin 项目。先解压canal.deployer 压缩包,再修改配置,如果Canal 和Canal Admin 不在同一台主机上部署(博主这里是部署在同一台主机上),需要修改Canal 的配置(conf/canal_local.properties )。
[root@localhost local]
[root@localhost local]
[root@localhost local]
[root@localhost canal-server]
配置修改如下图所示: 等启动Canal Admin 之后再启动Canal 。
部署Canal Admin
Canal Admin 设计上是为Canal 提供整体配置管理、节点运维等面向运维的功能,提供相对友好的WebUI 操作界面,方便更多用户快速和安全的操作。
解压文件和修改配置:
[root@localhost canal-server]
[root@localhost local]
[root@localhost local]
[root@localhost local]
[root@localhost canal-admin]
修改数据库相关配置,需要适配Mysql 8 。 Mysql 8 的驱动类名是com.mysql.cj.jdbc.Driver ,并且Mysql 8 需要配置serverTimezone (以下serverTimezone 配置都可以)。
serverTimezone=GMT%2B8
serverTimezone=GMT
serverTimezone=Asia/Shanghai
如果用户使用了sha256_password 认证,密码在传输过程中必须使用TLS 协议保护,如果RSA 公钥不可用,可以使用服务器提供的公钥;可以在连接中通过ServerRSAPublicKeyFile 指定服务器的RSA 公钥,或者使用allowPublicKeyRetrieval=true 参数以允许客户端从服务器获取公钥;但是需要注意的是allowPublicKeyRetrieval=true 可能会导致恶意的代理通过中间人攻击(MITM )获取到明文密码,所以默认是关闭的,必须显式开启。
Mysql 8 的密码加密方式为caching_sha2_password ,将其修改为mysql_native_password ,就可以不需要allowPublicKeyRetrieval=true 参数。
alter user 'kaven'@'%' identified with mysql_native_password by 'kaven';
flush privileges;
还要将Canal Admin 项目中的sql 文件导入Mysql 中(会生成用于管理Canal 的相关表)。
[root@localhost canal-admin]
Enter password:
mysql> source conf/canal_manager.sql
Query OK, 1 row affected, 2 warnings (0.06 sec)
Database changed
...
Query OK, 0 rows affected (0.00 sec)
mysql> exit
Bye
还需要更换Mysql 连接jar 包,可以在本地maven 仓库里面找,博主选择平时用的最新的8.0.22 版本。 使用下面这条命令来查看Mysql 版本:
select version();
博主这里的Mysql 版本是8.0.27 。 默认的Mysql 连接jar 包是5.1.48 版本,连接Mysql 8 会出问题。
[root@localhost canal-admin]
[root@localhost lib]
删除该jar 包。
[root@localhost lib]
使用Xftp 上传Mysql 8 的连接jar 包到Canal Admin 项目的lib 路径下。
[root@localhost lib]
./mysql-connector-java-8.0.22.jar
启动Canal Admin 。
[root@localhost lib]
[root@localhost canal-admin]
查看日志,发现日志文件不存在,说明启动失败了。
[root@localhost canal-admin]
tail: 无法打开"logs/admin.log" 读取数据: 没有那个文件或目录
在bin 目录下可以找到类似hs_err_pid20182.log 的日志文件。
[root@localhost canal-admin]
[root@localhost bin]
总用量 40
-rw-r--r--. 1 root root 6 12月 13 23:45 admin.pid
-rw-r--r--. 1 root root 18584 12月 13 23:45 hs_err_pid20182.log
-rwxr-xr-x. 1 root root 205 4月 19 2021 restart.sh
-rwxr-xr-x. 1 root root 747 4月 19 2021 startup.bat
-rwxr-xr-x. 1 root root 2047 4月 19 2021 startup.sh
-rwxr-xr-x. 1 root root 1362 4月 19 2021 stop.sh
由下图可知,Canal Admin 启动失败是由于分配2G 内存不成功导致的(因为虚拟机本身内存就只分配了2G )。 因此需要修改项目的JVM 堆内存配置,这个配置在启动脚本中设置。
[root@localhost bin]
初始堆内存和最大堆内存都设置成1G 。 再启动Canal Admin 。
[root@localhost bin]
再查看日志,如下图所示,说明启动成功了。 启动成功后,再关闭防火墙,让本地可以访问Canal Admin 。
[root@localhost bin]
本地访问192.168.1.199:8089 。 现在可以启动Canal 了。
[root@localhost bin]
[root@localhost canal-server]
查看日志,检查Canal 是否启动成功。
[root@localhost canal-server]
如下图所示,说明启动成功了。
Server & Instance
刚刚启动的server (Canal )已经在Canal Admin 上显示出来了,并且状态是启动。 可以对server 进行操作。 比如查看server 的日志。
新建instance 。 如下图所示进行操作即可。
example instance 也是启动状态。
可以查看example instance 的日志。
再新建一个other instance ,配置和example instance 一样,other Instance 的状态也是启动。 也可以查看other instance 的日志。 实现逻辑就是在Canal 项目的日志路径和配置路径下创建了对应instance 的相关文件。
[root@localhost canal-server]
总用量 0
drwxr-xr-x. 2 root root 47 12月 14 15:27 canal
drwxr-xr-x. 2 root root 25 12月 14 15:20 example
drwxr-xr-x. 2 root root 23 12月 14 15:34 other
[root@localhost canal-server]
总用量 16
-rwxrwxrwx. 1 root root 319 4月 19 2021 canal_local.properties
-rwxrwxrwx. 1 root root 6277 4月 19 2021 canal.properties
drwxrwxrwx. 2 root root 65 12月 14 15:17 example
-rwxrwxrwx. 1 root root 3437 4月 19 2021 logback.xml
drwxrwxrwx. 2 root root 39 12月 13 23:02 metrics
drwxr-xr-x. 2 root root 38 12月 14 15:36 other
drwxrwxrwx. 3 root root 149 12月 13 23:02 spring
[root@localhost canal-server]
总用量 156
-rw-r--r--. 1 root root 155648 12月 14 15:36 h2.mv.db
-rw-r--r--. 1 root root 40 12月 14 15:36 meta.dat
example instance 的相关文件在Canal 项目中默认存在,而配置信息以在Canal Admin 中的配置为准(其他instance 也一样),比如修改example instance 的数据库用户配置。 example instance 的日志中就会出现数据库拒绝访问的错误日志。 因此instance 的配置以Canal Admin 中的配置为准。
集成ZooKeeper
搭建ZooKeeper 可以参考下面这几篇博客:
启动ZooKeeper 并且关闭防火墙。
[root@localhost ~]
[root@localhost apache-zookeeper-3.6.3-bin]
ZooKeeper JMX enabled by default
Using config: /usr/local/apache-zookeeper-3.6.3-bin/bin/../conf/zoo.cfg
Starting zookeeper ... STARTED
[root@localhost apache-zookeeper-3.6.3-bin]
ZooKeeper JMX enabled by default
Using config: /usr/local/apache-zookeeper-3.6.3-bin/bin/../conf/zoo.cfg
Client port found: 9000. Client address: localhost. Client SSL: false.
Mode: standalone
[root@localhost apache-zookeeper-3.6.3-bin]
在Canal Admin 上添加集群,集群名称为zookeeper 。 修改zookeeper 集群的主配置。 主要是添加ZooKeeper 服务地址。 在zookeeper 集群下创建server (博主把之前创建的instance 和server 都删除了,因为server 不能修改所属集群配置,只能删除再重新创建)。 创建kaven server 成功,状态为启动。 在zookeeper 集群下创建instance 。 由下图所示,itkaven instance 由zookeeper 集群下的kaven server 运行,状态也是启动。 查看itkaven instance 的日志,很显然启动成功了。 因为zookeeper 集群下只有一个server ,即kaven server ,因此itkaven instance 肯定是在kaven server 上运行的。查看Canal 项目(zookeeper 集群下唯一的server )的日志文件和配置文件即可发现itkaven instance 的相关文件:
[root@localhost canal-server]
总用量 0
drwxr-xr-x. 2 root root 47 12月 14 15:27 canal
drwxr-xr-x. 2 root root 25 12月 14 15:20 example
drwxr-xr-x. 2 root root 25 12月 14 16:26 itkaven
drwxr-xr-x. 2 root root 23 12月 14 15:34 other
[root@localhost canal-server]
总用量 16
-rwxrwxrwx. 1 root root 319 4月 19 2021 canal_local.properties
-rwxrwxrwx. 1 root root 6277 4月 19 2021 canal.properties
drwxrwxrwx. 2 root root 65 12月 14 16:05 example
drwxr-xr-x. 2 root root 38 12月 14 16:27 itkaven
-rwxrwxrwx. 1 root root 3437 4月 19 2021 logback.xml
drwxrwxrwx. 2 root root 39 12月 13 23:02 metrics
drwxr-xr-x. 2 root root 38 12月 14 15:36 other
drwxrwxrwx. 3 root root 149 12月 13 23:02 spring
ZooKeeper 中也会保存一些数据(比如集群下的所有server 和instance 信息,以及instance 在哪个server 上运行)。
[root@localhost apache-zookeeper-3.6.3-bin]
[zk: 127.0.0.1:9000(CONNECTED) 0] ls -R /otter
/otter
/otter/canal
/otter/canal/cluster
/otter/canal/destinations
/otter/canal/cluster/192.168.1.199:11111
/otter/canal/destinations/itkaven
/otter/canal/destinations/itkaven/cluster
/otter/canal/destinations/itkaven/running
/otter/canal/destinations/itkaven/cluster/192.168.1.199:11111
[zk: 127.0.0.1:9000(CONNECTED) 1] get /otter/canal/destinations/itkaven/running
{"active":true,"address":"192.168.1.199:11111"}
HA机制设计
canal 的HA 分为两部分,canal server 和canal client 分别有对应的HA 实现:
canal server : 为了减少对mysql dump 的请求,不同server 上的instance 要求同一时间只能有一个处于running ,其他的处于standby 状态。canal client : 为了保证有序性,一个instance 同一时间只能由一个canal client 进行get/ack/rollback 操作,否则客户端接收无法保证有序。
整个HA 机制的控制主要是依赖了ZooKeeper 的几个特性,watcher 和EPHEMERAL 节点(和session 生命周期绑定)。
大致步骤:
canal server 要启动某个canal instance 时,都先向ZooKeeper 进行一次尝试启动判断 (创建EPHEMERAL 节点,谁创建成功就允许谁启动)。- 创建
ZooKeeper 节点成功后,该canal server 就启动对应的canal instance ,没有创建成功的canal instance 就会处于standby 状态。 - 一旦
ZooKeeper 发现canal server 创建的节点消失后,立即通知其他的canal server 再次进行步骤1 的操作,重新选出一个canal server 启动canal instance 。 canal client 每次进行connect 时,会首先向ZooKeeper 询问当前是谁启动了canal instance ,然后和其建立连接,一旦连接不可用,会重新尝试connect 。
canal client 的方式和canal server 的方式类似,也是利用ZooKeeper 抢占EPHEMERAL 节点的方式进行控制。
部署Canal 、Canal Admin 以及使用ZooKeeper 进行集群管理就介绍到这里,如果博主有说错的地方或者大家有不同的见解,欢迎大家评论补充。
|