canal原理的一些学习-1(canal的一些原理性介绍)

1. cannal 是什么,能做什么用

canal 的历史
  早期,阿里巴巴B2B公司因为存在杭州和美国双机房部署,存在跨机房同步的业务需求。不过早期的数据库同步业务,主要是基于trigger的方式获取增量变更,不过从2010年开始,阿里系公司开始逐步的尝试基于数据库的日志解析,获取增量变更进行同步,由此衍生出了增量订阅&消费的业务。
  基于数据库增量日志解析,提供增量数据订阅&消费,目前主要支持了mysql。

1.1 mysql的binlog

  它记录了所有的DDL和DML(除了数据查询语句)语句,以事件形式记录,还包含语句所执行的消耗的时间。主要用来备份和数据同步。

binlog 有三种模式:STATEMENT、ROW、MIXED

1.STATEMENT 记录的是执行的sql语句
2.ROW 记录的是真实的行数据记录
3.MIXED 记录的是1+2,优先按照1的模式记录

举例来说,下面的sql
update user set age=20

对应STATEMENT模式只有一条记录,对应ROW模式则有可能有成千上万条记录(取决数据库中的记录数)。

1.2 mysql 的主从复制过程

这里写图片描述

  1. Slave 上面的IO线程连接上 Master,并请求从指定日志文件的指定位置(或者从最开始的日志)之后的日志内容;
  2. Master 接收到来自 Slave 的 IO 线程的请求后,通过负责复制的 IO 线程根据请求信息读取指定日志指定位置之后的日志信息,返回给 Slave 端的 IO 线程。返回信息中除了日志所包含的信息之外,还包括本次返回的信息在 Master 端的 Binary Log 文件的名称以及在 Binary Log 中的位置;
  3. Slave 的 IO 线程接收到信息后,将接收到的日志内容依次写入到 Slave 端的Relay Log文件(mysql-relay-bin.xxxxxx)的最末端,并将读取到的Master端的bin-log的文件名和位置记录到master- info文件中,以便在下一次读取的时候能够清楚的高速Master“我需要从某个bin-log的哪个位置开始往后的日志内容,请发给我”
  4. Slave 的 SQL 线程检测到 Relay Log 中新增加了内容后,会马上解析该 Log 文件中的内容成为在 Master 端真实执行时候的那些可执行的 Query 语句,并在自身执行这些 Query。这样,实际上就是在 Master 端和 Slave 端执行了同样的 Query,所以两端的数据是完全一样的。
    当然这个过程本质上还是存在一定的延迟的。
    mysql的binlog文件长这个样子。
mysql-bin.003831
mysql-bin.003840  
mysql-bin.003849  
mysql-bin.003858 

1.3 canal能够同步数据的原理

理解了mysql的主从同步的机制再来看canal就比较清晰了,canal主要是听过伪装成mysql从server来向主server拉取数据。
这里写图片描述

  1. canal模拟mysql slave的交互协议,伪装自己为mysql slave,向mysql master发送dump协议
  2. mysql master收到dump请求,开始推送binary log给slave(也就是canal)
  3. canal解析binary log对象(原始为byte流)

2. quick start

直接引用 阿里的就不错,这里是一个阿里的单机版配置。
https://github.com/alibaba/canal/wiki/QuickStart
主要的点就是:

扫描二维码关注公众号,回复: 2241609 查看本文章
  1. 数据库配置,需要记录bin_log 需要使用row模式,需要创建用户给canal使用
  2. canal配置相应的主库地址,server_id在mysql的集群中不能重复,过滤哪些表使用的正则。
  3. 这个是一个单机的canal的搭建,并不是HA的模式。

3. canal 的设计

3.1 canal的设计理念

canal的组件化设计非常好,有点类似于tomcat的设计。使用组合设计,依赖倒置,面向接口的设计。
这里写图片描述

3.2 canal的组件有哪些

  1. canal server 这个代表了我们部署的一个canal 应用
  2. canal instance 这个代表了一个canal server中的多个 mysql instance ,从这一点说明一个canal server可以搜集多个库的数据,在canal中叫 destionation。

  每个canal instance 有多个组件构成。在conf/spring/default-instance.xml中配置了这些组件。他其实是使用了spring的容器来进行这些组件管理的。

3.3 instance 包含的组件

这里是一个cannalInstance工作所包含的大组件。截取自 conf/spring/default-instance.xml

        <bean id="instance" class="com.alibaba.otter.canal.instance.spring.CanalInstanceWithSpring">
                <property name="destination" value="${canal.instance.destination}" />
                <property name="eventParser">
                        <ref local="eventParser" />
                </property>
                <property name="eventSink">
                        <ref local="eventSink" />
                </property>
                <property name="eventStore">
                        <ref local="eventStore" />
                </property>
                <property name="metaManager">
                        <ref local="metaManager" />
                </property>
                <property name="alarmHandler">
                        <ref local="alarmHandler" />
                </property>
        </bean>  
  1. eventParser 最基本的组件,类似于mysql从库的dump线程,负责从master中获取bin_log这里写图片描述
  2. eventSink 数据的归集,使用设置的filter对bin log进行过滤,工作的过程如下。这里写图片描述
  3. eventStore 用来存储filter过滤后的数据,canal目前的数据只在这里存储,工作流程如下。 这里写图片描述
  4. metaManager 用来存储一些原数据,比如消费到的游标,当前活动的server等信息
  5. alarmHandler 报警,这个一般情况下就是错误日志,理论上应该是可以定制成邮件等形式,但是目前不支持

3.4 各个组件目前支持的类型

canal采用了spring bean container的方式来组装一个canal instance ,目的是为了能够更加灵活。

  1. eventParser 目前只有三种
    1.1. MysqlEventParser 用于解析mysql的日志
    1.2. GroupEventParser 多个eventParser的集合,理论上是对应了分表的情况,可以通过这个合并到一起
    1.3. RdsLocalBinlogEventParser 基于rds的binlog 的复制
  2. eventSink 目前只有EntryEventSink 就是基于mysql的binlog数据对象的处理操作
  3. eventStore 目前只有一种 MemoryEventStoreWithBuffer,内部使用了一个ringbuffer 也就是说canal解析的数据都是存在内存中的,并没有到zookeeper当中。
  4. metaManager 这个比较多,其实根据元数据存放的位置可以分为三大类,memory,file,zookeeper

  canal通过这些组件的选取可以达到不同使用场景的效果,比如单机的话,一般使用file来存储metadata就行了,HA的话一般使用zookeeper来存储metadata。

4. canal的工作过程

4.1 启动时去MySQL 进行dump操作的binlog 位置确定

  工作的过程。在启动一个canal instance 的时候,首先启动一个eventParser 线程来进行数据的dump 当他去master拉取binlog的时候需要binlog的位置,这个位置的确定是按照如下的顺序来确定的(这个地方讲述的是HA模式哈)。

  1. 在启动的时候判断是否使用zookeeper,如果是zookeeper,看能否拿到 cursor (也就是binlog的信息),如果能够拿到,把这个信息存到内存中(MemoryLogPositionManager),然后拿这个信息去mysql中dump binlog
  2. 通过1拿不到的话(一般是zookeeper当中每一,比如第一次搭建的时候,或者因为某些原因zk中的数据被删除了),就去配置文件配置当中的去拿,把这个信息存到内存中(MemoryLogPositionManager),然后拿这个信息去mysql中dump binlog
  3. 通过2依然没有拿到的话,就去mysql 中执行一个sql show master status 这个语句会显示当前mysql binlog最后位置的信息,也就是刚写入的binlog所在的位置信息。把这个信息存到内存中(MemoryLogPositionManager),然后拿这个信息去mysql中dump binlog。

  后面的eventParser的操作就会以内存中(MemoryLogPositionManager)存储的binlog位置去master进行dump操作了。
mysql的show master status 操作

mysql>
mysql> show master status\G
*************************** 1. row ***************************
             File: mysql-bin.000028
         Position: 635762367
     Binlog_Do_DB:
 Binlog_Ignore_DB:
Executed_Gtid_Set: 18db0532-6a08-11e8-a13e-52540042a113:1-2784514,
318556ef-4e47-11e6-81b6-52540097a9a8:1-30002,
ac5a3780-63ad-11e8-a9ac-52540042a113:1-5,
be44d87c-4f25-11e6-a0a8-525400de9ffd:1-156349782
1 row in set (0.00 sec)

4.2 数据在dump回来之后进行的归集(sink)和存储(store)

sink操作是可以支撑将多个eventParser的数据进行过滤filter

filter使用的是instance.properties中配置的filter,当然这个filter也可以由canal的client端在进行subscribe的时候进行设置。如果在client端进行了设置,那么服务端配置文件instance.properties的配置都会失效

sink 之后将过滤后的数据存储到eventStore当中去。
  目前eventStore的实现只有一个MemoryEventStoreWithBuffer,也就是基于内存的ringbuffer,使用这个store有一个特点,这个ringbuffer是基于内存的,大小是有限制的(bufferSize = 16 * 1024 也就是16M),所以,当canal的客户端消费比较慢的时候,ringbuffer中存满了就会阻塞sink操作,那么正读取mysql binlogeventParser线程也会受阻。
  这种设计其实也是有道理的。 因为canal的操作是pull 模型,不是producer push的模型,所以他没必要存储太多数据,这样就可以避免了数据存储和持久化管理的一些问题。使数据管理的复杂度大大降低。

  上面这些整个是canal的parser 线程的工作流程,主要对应的就是将数据从mysql搞下来,做一些基本的归集和过滤,然后存储到内存中。

4.3 binlog的消费者

  canal从mysql订阅了binlog以后主要还是想要给消费者使用。那么binlog是在什么时候被消费呢。这就是另一条主线了。就像咱们做一个toC的系统,管理系统是必须的,用户使用的app或者web又是一套,eventParser 线程就像是管理系统,往里面录入基础数据。canal的client就像是app端一样,是这些数据的消费方。
  binlog的主要消费者就是canal的client端。使用的协议是基于tcp的google.protobuf,当然tcp的模式是io多路复用,也就是nio。当我们的client发起请求之后,canal的server端就会从eventStore中将数据传输给客户端。根据客户端的ack机制,将binlog的元数据信息定期同步到zookeeper当中。

差不多主要的操作就是这些吧。

5. canal的目录结构(不包含lib目录)

配置父目录:
在下面可以看到,

canal
├── bin
   ├── canal.pid
   ├── startup.bat
   ├── startup.sh
   └── stop.sh
└── conf
    ├── canal.properties
    ├── gamer ---目录
    ├── ww_social ---目录
    ├── wother ---目录
    ├── nihao ---目录
    ├── liveim ---目录
    ├── logback.xml
    ├── spring ---目录
    ├── ym ---目录
    └── xrm_ppp ---目录

这里是全部展开的目录

canal
├── bin
│   ├── canal.pid
│   ├── startup.bat
│   ├── startup.sh
│   └── stop.sh
└── conf
    ├── canal.properties
    ├── game_center
    │   └── instance.properties
    ├── ww_social
    │   ├── h2.mv.db
    │   ├── h2.trace.db
    │   └── instance.properties
    ├── wwother
    │   ├── h2.mv.db
    │   └── instance.properties
    ├── nihao
    │   ├── h2.mv.db
    │   ├── h2.trace.db
    │   └── instance.properties
    ├── movie
    │   ├── h2.mv.db
    │   └── instance.properties
    ├── logback.xml
    ├── spring
    │   ├── default-instance.xml
    │   ├── file-instance.xml
    │   ├── group-instance.xml
    │   ├── local-instance.xml
    │   ├── memory-instance.xml
    │   └── tsdb
    │       ├── h2-tsdb.xml
    │       ├── mysql-tsdb.xml
    │       ├── sql
    │       └── sql-map
    └── ym
        └── instance.properties

猜你喜欢

转载自blog.csdn.net/u013200380/article/details/80963569
今日推荐