目录
- 前言
- canal介绍
- canal工作原理
- mysql配置
- canal架构
- canal-ha架构
- canal应用场景
- 总结
前言
前两篇文章老顾介绍了基于binlog日志,同步多机房的mysql;推荐使用canal组件;今天老顾就来介绍一下canal基本原理,以及一些常用的使用场景。
canal介绍
Canal是阿里开源的一款基于Mysql数据库binlog的增量订阅和消费组件,通过它可以订阅数据库的binlog日志,然后进行一些数据消费,如数据镜像、数据异构、数据索引、缓存更新等。相对于消息队列,通过这种机制可以实现数据的有序化和一致性。
github地址:https://github.com/alibaba/canal
完整wiki地址:https://github.com/alibaba/canal/wiki
Canal工作原理
原理很简单:
- Canal模拟MySQL的slave的交互协议,伪装成mysql slave,并将转发协议发送到MySQL Master服务器。
- MySQL Master接收到存储请求并开始将二进制日志推送到slave(即canal)。
- Canal将二进制日志对象解析为自己的数据类型(原始字节流)
如图所示:
![5461afc92e896f2654c90f70cc2db968.png](https://i-blog.csdnimg.cn/blog_migrate/bc17419ca6ded54b7e3907bf31e5783b.jpeg)
mysql配置
基于binlog则需要开启mysql的binlog日志
(1)查看当前mysql是否开启binlog模式。
SHOW VARIABLES LIKE '%log_bin%'
![fdeacac784d42bd7a65b90ac38c03bbb.png](https://i-blog.csdnimg.cn/blog_migrate/bacb27dc34b9f1ecb55550f46e77c86d.jpeg)
(2)修改/etc/my.cnf 需要开启binlog模式。
[mysqld]log-bin=mysql-binbinlog-format=ROWserver_id=1
修改完成之后,重启mysqld的服务。
(3) 进入mysql
mysql -h localhost -u root -p
(4) 创建账号 用于测试使用
使用root账号创建用户并授予权限
create user canal@'%' IDENTIFIED by 'canal';GRANT SELECT, REPLICATION SLAVE, REPLICATION CLIENT,SUPER ON *.* TO 'canal'@'%';FLUSH PRIVILEGES;
Canal架构
![66ce589dcc7890037bb2566962ae95b6.png](https://i-blog.csdnimg.cn/blog_migrate/b5cbfd6749ea5fe2c5c42f6def353ee4.jpeg)
server代表一个canal运行实例,对应于一个jvm
instance对应于一个数据队列
instance模块:
- eventParser (数据源接入,模拟slave协议和master进行交互,协议解析)
- eventSink (Parser和Store链接器,进行数据过滤,加工,分发的工作)
- eventStore (数据存储)
- metaManager (增量订阅&消费信息管理器)
Canal-HA机制
canal是支持HA的,其实现机制是依赖zookeeper来实现的,用到的特性有watcher和EPHEMERAL节点(和session生命周期绑定),与HDFS的HA类似。
canal的ha分为两部分,canal server和canal client分别有对应的ha实现
- canal server: 为了减少对mysql dump的请求,不同server上的instance(不同server上的相同instance)要求同一时间只能有一个处于running,其他的处于standby状态(standby是instance的状态)。
- canal client: 为了保证有序性,一份instance同一时间只能由一个canal client进行get/ack/rollback操作,否则客户端接收无法保证有序。
server ha的架构图如下:
![0e8b73b02cd7fee8f66d0f48c2f0bb04.png](https://i-blog.csdnimg.cn/blog_migrate/d5e8b555162029e079db2bff02df18a8.jpeg)
大致步骤:
- canal server要启动某个canal instance时都先向zookeeper_进行一次尝试启动判断_(实现:创建EPHEMERAL节点,谁创建成功就允许谁启动)
- 创建zookeeper节点成功后,对应的canal server就启动对应的canal instance,没有创建成功的canal instance就会处于standby状态。
- 一旦zookeeper发现canal server A创建的instance节点消失后,立即通知其他的canal server再次进行步骤1的操作,重新选出一个canal server启动instance。
- canal client每次进行connect时,会首先向zookeeper询问当前是谁启动了canal instance,然后和其建立链接,一旦链接不可用,会重新尝试connect。
Canal Client的方式和canal server方式类似,也是利用zookeeper的抢占EPHEMERAL节点的方式进行控制.
Canal应用场景
1、同步缓存redis/全文搜索ES
canal一个常见应用场景是同步缓存/全文搜索,当数据库变更后通过binlog进行缓存/ES的增量更新。当缓存/ES更新出现问题时,应该回退binlog到过去某个位置进行重新同步,并提供全量刷新缓存/ES的方法,如下图所示。
之前的老顾有篇文章中介绍了缓存与数据库一致性的问题,有一个方案就是binlog日志;小伙伴们可以去看看
![16927cfee77d74bdda87b89aab3ed731.png](https://i-blog.csdnimg.cn/blog_migrate/9507a08b96705cf798a6b68f0bb855ba.jpeg)
2、下发任务
另一种常见应用场景是下发任务,当数据变更时需要通知其他依赖系统。其原理是任务系统监听数据库变更,然后将变更的数据写入MQ/kafka进行任务下发,比如商品数据变更后需要通知商品详情页、列表页、搜索页等先关系统。这种方式可以保证数据下发的精确性,通过MQ发送消息通知变更缓存是无法做到这一点的,而且业务系统中不会散落着各种下发MQ的代码,从而实现了下发归集,如下图所示。
![2d83563b7ebde2e5677373122184f134.png](https://i-blog.csdnimg.cn/blog_migrate/46a5d9501c1b4f6ceed4afcf796c088a.jpeg)
3、数据异构
在大型网站架构中,DB都会采用分库分表来解决容量和性能问题,但分库分表之后带来的新问题。比如不同维度的查询或者聚合查询,此时就会非常棘手。一般我们会通过数据异构机制来解决此问题。
所谓的数据异构,那就是将需要join查询的多表按照某一个维度又聚合在一个DB中。让你去查询。canal就是实现数据异构的手段之一。
![b83d98ec8975f87865175523d5f6b807.png](https://i-blog.csdnimg.cn/blog_migrate/f602ab897c7f8b7d6d545a5d09f6af4d.jpeg)
用canal来订阅binlog,可异构系统
![c64813837aac5534154ddd2461e3a4d8.png](https://i-blog.csdnimg.cn/blog_migrate/28fd218682a095dd74fcee6c9f65fc24.jpeg)
4、冗余字段
在微服务设计中,每个服务都会对应数据库以及表;虽然微服务很强大,增加很多系统灵活性;但是也增加了复杂度;如:数据库和表的独立分离,导致有些join查询不便。我们常用的方法就是设计表字段的冗余。
但是冗余方案,会有一些问题
![4fb07ccfa23df6cc1dd8072bc3d053ed.png](https://i-blog.csdnimg.cn/blog_migrate/9b25268bd5251339a0b88583c1a65103.jpeg)
上面2张表,位于不同的微服务,即不同的数据库。为了方便在查询order订单的时候,显示下单用户的真实姓名;就在order表中对用户truename进行了冗余设计。但是如果user的服务对user的truename进行更新修改;那么就导致了order表中的truename与user的truename不一致。
上面的场景在我们实际开发过程是非常常见的。当然为了解决这个问题,用binlog方式就非常简单了;利用canal组件即可解决。
总结
老顾今天介绍了基于binlog的canal的基本原理,以及使用场景。当然不限于以上的使用场景,只要跟mysql的binlog有关都可以。下篇文章老顾会重点讲解canal的使用方法。
---End---