【Canal】数据同步的终极解决方案,阿里巴巴开源的Canal框架当之无愧!!

载录博客园文章

https://www.cnblogs.com/binghe001/p/13445117.html

写在前面

在当今互联网行业,尤其是现在分布式、微服务开发环境下,为了提高搜索效率,以及搜索的精准度,会大量使用Redis、Memcached等NoSQL数据库,也会使用大量的Solr、Elasticsearch等全文检索服务。那么,这个时候,就会有一个问题需要我们来思考和解决:那就是数据同步的问题!如何将实时变化的数据库中的数据同步到Redis/Memcached或者Solr/Elasticsearch中呢?

互联网背景下的数据同步需求

在当今互联网行业,尤其是现在分布式、微服务开发环境下,为了提高搜索效率,以及搜索的精准度,会大量使用Redis、Memcached等NoSQL数据库,也会使用大量的Solr、Elasticsearch等全文检索服务。那么,这个时候,就会有一个问题需要我们来思考和解决:那就是数据同步的问题!如何将实时变化的数据库中的数据同步到Redis/Memcached或者Solr/Elasticsearch中呢?

例如,我们在分布式环境下向数据库中不断的写入数据,而我们读数据可能需要从Redis、Memcached或者Elasticsearch、Solr等服务中读取。那么,数据库与各个服务中数据的实时同步问题,成为了我们亟待解决的问题。

试想,由于业务需要,我们引入了Redis、Memcached或者Elasticsearch、Solr等服务。使得我们的应用程序可能会从不同的服务中读取数据,如下图所示。

本质上讲,无论我们引入了何种服务或者中间件,数据最终都是从我们的MySQL数据库中读取出来的。那么,问题来了,如何将MySQL中的数据实时同步到其他的服务或者中间件呢?

注意:为了更好的说明问题,后面的内容以MySQL数据库中的数据同步到Solr索引库为例进行说明。

数据同步解决方案

1.在业务代码中同步

在增加、修改、删除之后,执行操作Solr索引库的逻辑代码。例如下面的代码片段。

 

优点:

操作简便。

缺点:

业务耦合度高。

执行效率变低。

2.定时任务同步

在数据库中执行完增加、修改、删除操作后,通过定时任务定时的将数据库的数据同步到Solr索引库中。

定时任务技术有:SpringTask,Quartz。

哈哈,还有我开源的mykit-delay框架,开源地址为:https://github.com/sunshinelyz/mykit-delay。

这里执行定时任务时,需要注意的一个技巧是:第一次执行定时任务时,从MySQL数据库中以时间字段进行倒序排列查询相应的数据,并记录当前查询数据的时间字段的最大值,以后每次执行定时任务查询数据的时候,只要按时间字段倒序查询数据表中的时间字段大于上次记录的时间值的数据,并且记录本次任务查询出的时间字段的最大值即可,从而不需要再次查询数据表中的所有数据。

注意:这里所说的时间字段指的是标识数据更新的时间字段,也就是说,使用定时任务同步数据时,为了避免每次执行任务都会进行全表扫描,最好是在数据表中增加一个更新记录的时间字段。

优点:

同步Solr索引库的操作与业务代码完全解耦。

缺点:

数据的实时性并不高。

3.通过MQ实现同步

在数据库中执行完增加、修改、删除操作后,向MQ中发送一条消息,此时,同步程序作为MQ中的消费者,从消息队列中获取消息,然后执行同步Solr索引库的逻辑。

我们可以使用下图来简单的标识通过MQ实现数据同步的过程。

我们可以使用如下代码实现这个过程。

 

优点:

业务代码解耦,并且能够做到准实时。

缺点:

需要在业务代码中加入发送消息到MQ的代码,数据调用接口耦合。

4.通过Canal实现实时同步

Canal是阿里巴巴开源的一款数据库日志增量解析组件,通过Canal来解析数据库的日志信息,来检测数据库中表结构和数据的变化,从而更新Solr索引库。

使用Canal可以做到业务代码完全解耦,API完全解耦,可以做到准实时。

Canal简介

阿里巴巴MySQL数据库binlog增量订阅与消费组件,基于数据库增量日志解析,提供增量数据订阅与消费,目前主要支持了MySQL。

Canal开源地址:https://github.com/alibaba/canal

Canal工作原理

MySQL主从复制的实现

从上图可以看出,主从复制主要分成三步:

  • Master节点将数据的改变记录到二进制日志(binary log)中(这些记录叫做二进制日志事件,binary log events,可以通过show binlog events进行查看)。
  • Slave节点将Master节点的二进制日志事件(binary log events)拷贝到它的中继日志(relay log)。
  • Slave节点重做中继日志中的事件将改变反映到自己本身的数据库中。

Canal内部原理

首先,我们来看下Canal的原理图,如下所示。

原理大致描述如下:

  • Canal 模拟 MySQL slave 的交互协议,伪装自己为 MySQL Slave ,向 MySQL Master 发送dump 协议
  • MySQL Master 收到 dump 请求,开始推送 binary log 给 Slave (即 Canal )
  • Canal 解析 binary log 对象(原始为 byte 流)

Canal内部结构

说明如下:

  • Server:代表一个Canal运行实例,对应一个JVM进程。
  • Instance:对应一个数据队列(1个Server对应1个或者多个Instance)。

接下来,我们再来看下Instance下的子模块,如下所示。

  • EventParser:数据源接入,模拟Slave协议和Master节点进行交互,协议解析。
  • EventSink:EventParser和EventStore的连接器,对数据进行过滤、加工、归并和分发等处理。
  • EventSore:数据存储。
  • MetaManager:增量订阅和消费信息管理。

Canal环境准备

设置MySQL远程访问

 

MySQL配置

注意:这里的MySQL是基于5.7版本进行说明的。

Canal的原理基于MySQL binlog技术,所以,要想使用Canal就要开启MySQL的binlog写入功能,建议配置binlog的模式为row。

可以在MySQL命令行输入如下命令来查看binlog的模式。

 

执行效果如下所示。

可以看到,在MySQL中默认的binlog格式为STATEMENT,这里我们需要将STATEMENT修改为ROW。修改/etc/my.cnf文件。

 

在[mysqld]下面新增如下三项配置。

 

修改完my.cnf文件后,需要重启MySQL服务。

 

接下来,我们再次查看binlog模式。

 

可以看到,此时,MySQL的binlog模式已经被设置为ROW了。

MySQL创建用户授权

Canal的原理是模式自己为MySQL Slave,所以一定要设置MySQL Slave的相关权限。这里,需要创建一个主从同步的账户,并且赋予这个账户相关的权限。

 

Canal部署安装

下载Canal

这里,我们以Canal 1.1.1版本进行说明,小伙伴们可以到链接 https://github.com/alibaba/canal/releases/tag/canal-1.1.1 下载Canal 1.1.1版本。

上传解压

将下载好的Canal安装包,上传到服务器,并执行如下命令进行解压

 

解压后的目录如下所示。

各目录的说明如下:

  • bin:存储可执行脚本。
  • conf:存放配置文件。
  • lib:存放其他依赖或者第三方库。
  • logs:存放的是日志文件。

修改配置文件

在Canal的conf目录下有一个canal.properties文件,这个文件中配置的是Canal Server相关的配置,在这个文件中有如下一行配置。

 

这里的example就相当于Canal的一个Instance,可以在这里配置多个Instance,多个Instance之间以逗号分隔即可。同时,这里的example也对应着Canal的conf目录下的一个文件夹。也就是说,Canal中的每个Instance实例都对应着conf目录下的一个子目录。

接下来,我们需要修改Canal的conf目录下的example目录的一个配置文件instance.properties。

 

修改如下配置项。

 

选项含义:

  • canal.instance.mysql.slaveId : mysql集群配置中的serverId概念,需要保证和当前mysql集群中id唯一;
  • canal.instance.master.address: mysql主库链接地址;
  • canal.instance.dbUsername : mysql数据库帐号;
  • canal.instance.dbPassword : mysql数据库密码;
  • canal.instance.defaultDatabaseName : mysql链接时默认数据库;
  • canal.instance.connectionCharset : mysql 数据解析编码;
  • canal.instance.filter.regex : mysql 数据解析关注的表,Perl正则表达式.

启动Canal

配置完Canal后,就可以启动Canal了。进入到Canal的bin目录下,输入如下命令启动Canal。

 

测试Canal

导入并修改源码

这里,我们使用Canal的源码进行测试,下载Canal的源码后,将其导入到IDEA中。

接下来,我们找到example下的SimpleCanalClientTest类进行测试。这个类的源码如下所示。

 

可以看到,这个类中,使用的destination为example。在这个类中,我们只需要将IP地址修改为Canal Server的IP即可。

具体为:将如下一行代码。

 

修改为:

 

由于我们在配置Canal时,没有指定用户名和密码,所以,我们还需要将如下代码。

 

修改为:

 

修改完成后,运行main方法启动程序。

测试数据变更

接下来,在MySQL中创建一个canaldb数据库。

 

此时会在IDEA的命令行输出相关的日志信息。

 

接下来,我在canaldb数据库中创建数据表,并对数据表中的数据进行增删改查,程序输出的日志信息如下所示。

 

数据同步实现

需求

将数据库数据的变化, 通过canal解析binlog日志, 实时更新到solr的索引库中。

具体实现

创建工程

创建Maven工程mykit-canal-demo,并在pom.xml文件中添加如下配置。

 

创建log4j配置文件

在工程的src/main/resources目录下创建log4j.properties文件,内容如下所示。

 

创建实体类

在io.mykit.canal.demo.bean包下创建一个Book实体类,用于测试Canal的数据传输,如下所示。

 

其中,我们在Book实体类中,使用Solr的注解@Field定义了实体类字段与Solr域之间的关系。

各种工具类的实现

接下来,我们就在io.mykit.canal.demo.utils包下创建各种工具类。

  • BinlogValue

用于存储binlog分析的每行每列的value值,代码如下所示。

 
  • CanalDataParser

用于解析数据,代码如下所示。

 
  • DateUtils

时间工具类,代码如下所示。

 
  • InnerBinlogEntry

Binlog实体类,代码如下所示。

 
  • JacksonUtil

Json工具类,代码如下所示。

 

同步程序的实现

准备好实体类和工具类后,我们就可以编写同步程序来实现MySQL数据库中的数据实时同步到Solr索引库了,我们在io.mykit.canal.demo.main包中常见MykitCanalDemoSync类,代码如下所示。

 

接下来,启动SyncDataBootStart类的main方法,监听Canal Server,而Canal Server监听MySQL binlog的日志变化,一旦MySQL的binlog日志发生变化,则SyncDataBootStart会立刻收到变更信息,并将变更信息解析成Book对象实时更新到Solr库中。如果在MySQL数据库中删除了数据,则也会实时删除Solr库中的数据。

部分参考Canal官方文档:https://github.com/alibaba/canal

重磅福利

关注「 冰河技术 」微信公众号,后台回复 “设计模式” 关键字领取《深入浅出Java 23种设计模式》PDF文档。回复“Java8”关键字领取《Java8新特性教程》PDF文档。回复“限流”关键字获取《亿级流量下的分布式限流解决方案》PDF文档,三本PDF均是由冰河原创并整理的超硬核教程,面试必备!!

好了,今天就聊到这儿吧!别忘了点个赞,给个在看和转发,让更多的人看到,一起学习,一起进步!!

写在最后

如果你觉得冰河写的还不错,请微信搜索并关注「 冰河技术 」微信公众号,跟冰河学习高并发、分布式、微服务、大数据、互联网和云原生技术,「 冰河技术 」微信公众号更新了大量技术专题,每一篇技术文章干货满满!不少读者已经通过阅读「 冰河技术 」微信公众号文章,吊打面试官,成功跳槽到大厂;也有不少读者实现了技术上的飞跃,成为公司的技术骨干!如果你也想像他们一样提升自己的能力,实现技术能力的飞跃,进大厂,升职加薪,那就关注「 冰河技术 」微信公众号吧,每天更新超硬核技术干货,让你对如何提升技术能力不再迷茫!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值