概述
在大型网站架构中,DB都会采用分库分表来解决容量和性能问题,但是分库分表之后带来了新的问题,比如不同维度的查询或者聚合查询,此时就会非常棘手。一般我们会通过数据异构机制来解决此问题。
如下图所示,为了提升系统的接单能力,我们会对订单表进行分库分表,但是,随之而来的问题是:用户怎么查询自己的订单列表呢?一种办法是扫描所有的订单表,然后进行聚合,但是这种方式在大流量系统架构中肯定是不行的。另一种办法是双写,但是双写的一致性又没法保证。还有一种办法就是订阅数据库变更日志,比如订阅MySQL的binlog日志模拟数据库的主从同步机制,然后解析变更日志将数据写到订单列表,从而实现数据异构,这种机制也能保证数据的一致性。
除了可以进行订单列表的异构,像商家维度的异构、ES搜索异构、订单缓存异构等都可以通过这种方式解决。
Canal介绍
canal [kə’næl],译意为水道/管道/沟渠,主要用途是基于 MySQL 数据库增量日志解析,提供增量数据订阅和消费
早期阿里巴巴因为杭州和美国双机房部署,存在跨机房同步的业务需求,实现方式主要是基于业务 trigger 获取增量变更。从 2010 年开始,业务逐步尝试数据库日志解析获取增量变更进行同步,由此衍生出了大量的数据库增量订阅和消费业务。
基于日志增量订阅和消费的业务包括
- 数据库镜像
- 数据库实时备份
- 索引构建和实时维护(拆分异构索引、倒排索引等)
- 业务 cache 刷新
- 带业务逻辑的增量数据处理
- 当前的 canal 支持源端 MySQL 版本包括 5.1.x , 5.5.x , 5.6.x , 5.7.x , 8.0.x
MySQL主从工作原理
MySQL主备复制原理
- MySQL master 将数据变更写入二进制日志( binary log, 其中记录叫做二进制日志事件binary log events,可以通过 show binlog events 进行查看)
- MySQL slave 将 master 的 binary log events 拷贝到它的中继日志(relay log)
- MySQL slave 重放 relay log 中事件,将数据变更反映它自己的数据
canal 的工作原理
- canal 模拟 MySQL slave 的交互协议,伪装自己为 MySQL slave ,向MySQL master 发送dump 协议
- MySQL master 收到 dump 请求,开始推送 binary log 给 slave (即 canal )
- canal 解析 binary log 对象(原始为 byte 流)
MySQL数据库配置
修改my.cnf配置文件的如下信息。
[mysqld]
log-bin=mysql-bin #开启二进制日志
binlog-format=ROW #使用row模式,不是使用statement或者mixed模式
server_id=1 #配置主数据库ID,不能和从数据库重复
binlog提供了三种记录模式。
1. row:记录的是修改的记录信息,而不是执行的SQL,二进制日志文件会占用更大的空间,当执行alter table修改表结构造成记录变更时,该表的每一条记录都会被记录到日志中。
2.statement:每一条修改数据的SQL都会被记录在binlog中,其缺点很明显,比如我们使用了MySQL系统函数,可能会导致主从数据不一致。
3.mixed:一般SQL使用statement模式记录,特殊操作如一些系统函数,则采用row模式记录。
在使用Canal时建议使用row模式。
另外,在MySQL中执行“show binary logs”,将看到当前有哪些二进制日志文件及其大小。
接下来,我们要为Canal创建一个复制账号,并为其授权查询和复制权限。
# 创建账号
CREATE USER canal IDENTIFIED BY 'canal';
# 授予权限
GRANT SELECT, REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'canal'@'%';
# 更改加密规则
ALTER USER 'canal'@'%' IDENTIFIED BY 'canal' PASSWORD EXPIRE NEVER;
# 更改canal密码
ALTER USER 'canal'@'%' IDENTIFIED WITH mysql_native_password BY 'canal';
# 刷新并应用
FLUSH PRIVILEGES;
重启数据库后,测试 my.cnf 配置是否生效:
show variables like 'log_bin';
show variables like 'binlog_format';
show master status;
Canal环境搭建(不使用canal-admin监控的配置)
下载Canal镜像:
docker pull canal/canal-server:v1.1.4;
生成canal-server容器:
docker run -d --name canal-server -p 11111:11111 canal/canal-server:v1.1.4
查看Docker中运行的容器:
docker ps
canal-server的配置修改:
进入canal-server容器:
docker exec -it canal-server bash;
tail -f canal-server/logs/example/example.log
这里看日志可以看到连接mysql数据库失败的错误:
编辑Canal的instance.properties文件:
vi canal-server/conf/example/instance.properties
保存退出重启canal-server容器:
docker restart canal-server
进入canal-server容器查看日志:
docker exec -it canal-server bash
tail -100f canal-server