4.Otter操作简介

Adminguide

1.几点说明

otter系统自带了manager,所以简化了一些admin管理上的操作成本,比如可以通过manager发布同步任务配置,接收同步任务反馈的状态信息等。

目前manager的操作可分为两部分:

  • 同步配置管理
  1. 添加数据源
  2. canal解析配置
  3. 添加数据表
  4. 同步任务
  • 同步状态查询
  1. 查询延迟
  2. 查询吞吐量
  3. 查询同步进度
  4. 查询报警&异常日志

manager的用户权限在设计的时候,主要分为三类:

  • ADMIN : 超级管理员
  • OPERATOR : 普通用户,管理某个同步任务下的同步配置,添加数据表,修改canal配置等
  • ANONYMOUS : 匿名用户,只能进行同步状态查询的操作.

2.Manager配置介绍

deep edited this page on 19 Dec 2017 · 7 revisions

2.1 操作演示

演示视频(5分钟教你配置一个同步任务):请点击图片或者这里


演示说明:
  1. 搭建一个数据库同步任务,源数据库ip为:10.20.144.25,目标数据库ip为:10.20.144.29. 源数据库已开启binlog,并且binlog_format为ROW.
mysql> show variables like '%binlog_format%';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| binlog_format | ROW   |
+---------------+-------+
  1. 数据同步精确到一张表进行测试,测试的表名为test.example,简单包含两个子段,测试过程中才创建.

  2. 配置完成后,手动在源库插入数据,然后快速在目标库进行查看数据,验证数据是否同步成功.


视频中的演示文本:

CREATE TABLE  `test`.`example` (
  `id` int(11)  NOT NULL AUTO_INCREMENT,
  `name` varchar(32) COLLATE utf8_bin DEFAULT NULL ,
   PRIMARY KEY (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

insert into test.example(id,name) values(null,'hello');

-----
Otter QuickStart 如何配置一个任务
-----
操作步骤:
1.  添加数据库
    a.  源库 jdbc:mysql://10.20.144.25:3306
    b.  目标库 jdbc:mysql://10.20.144.29:3306
2.  添加canal
    a.  提供数据库ip信息 
3.  添加同步表信息
    a.  源数据表 test.example
    b.  目标数据表 test.example
4.  添加channel
5.  添加pipeline
    a.  选择node节点
    b.  选择canal
6.  添加同步映射规则
    a.  定义源表和目标表的同步关系
7.  启动
8.  测试数据

2.2 通道配置说明

2.2.1 多种同步方式配置

a. 单向同步

单向同步为最基本的同步方式,目前支持mysql -> mysql/oracle的同步.

基本配置方式就如操作视频中所演示的,操作步骤:

配置一个channel
配置一个pipeline
对应node机器选择时,建议遵循:S/E节点选择node需尽可能离源数据库近,T/L节点选择node则离目标数据库近. 如果无法提供双节点,则选择离目标数据库近的node节点相对合适.
配置一个canal
定义映射关系.
canal中配置解析的数据库ip需要和映射关系中源表对应的数据库ip一致. ps. 映射关系进行匹配的时候是基于表名,虽然数据库ip不匹配也会是有效.

b. 双向同步

双向同步可以理解为两个单向同步的组合,但需要额外处理避免回环同步. 回环同步算法: Otter双向回环控制 .

同时,因为双向回环控制算法会依赖一些系统表,需要在需要做双向同步的数据库上初始化所需的系统表.

获取初始sql:

wget https://raw.github.com/alibaba/otter/master/node/deployer/src/main/resources/sql/otter-system-ddl-mysql.sql

配置上相比于单向同步有一些不同,操作步骤:

配置一个channel
配置两个pipeline
注意:两个单向的canal和映射配置,在一个channel下配置为两个pipeline. 如果是两个channel,每个channel一个pipeline,将不会使用双向回环控制算法,也就是会有重复回环同步.
每个pipeline各自配置canal,定义映射关系

c. 双A同步

双A同步相比于双向同步,主要区别是双A机房会在两地修改同一条记录,而双向同步只是两地的数据做互相同步,两地修改的数据内容无交集.

所以双A同步需要额外处理数据同步一致性问题. 同步一致性算法:Otter数据一致性 ,目前开源版本主要是提供了单向回环补救的一致性方案.

双A同步相比于双向同步,整个配置主要是一些参数上有变化,具体步骤:

  1. 配置一个channel

    image
  2. 配置两个pipeline

    image
  • 注意:除了需要定义一个主站点外,需要在高级设置中将一个pipeline的“支持DDL”设置为false,另一个设置为true,否则将提示“一个channel中只允许开启单向ddl同步!”错误
    每个pipeline各自配置canal,定义映射关系
d. 级联同步

单向同步/双向同步,都是针对一个channel下的多pipeline配置进行控制,是否可以使用多个channel完成类似级联同步的功能.

几种级联同步.

  • A->B->C ,A单向同步到B,B再单向同步到C
  • A<->B->C,A和B组成一个双向,B再单向同步到C
  • A<->B<-C,A和B组成一个双向,C将数据单向同步B,也就是B是一个接受多M同步写入的的节点,目前mysql不支持
  • A<->B->C,B-/->D,A和B组成一个双向,B再单向同步到C,但A同步到B的数据不同步到D,但B地写入的数据同步到D,目前mysql不支持.
    对应操作步骤:
  1. 目前channel之间的级联同步,不需要设置任何参数,只要通过canal进行binlog解析即可.
  2. 针对级联屏蔽同步,需要利用到自定义同步标记的功能,比如A->B,B同步到C但不同步到D。需要在A->B的同步高级参数里定义NOT_DDD,然后在B同步到D的高级参数里也定义NOT_DDD.
  3. image
e. 多A同步

基于以上的单向/双向/双A/级联同步,可以随意搭建出多A同步,不过目前受限于同步数据的一致性算法,只能通过星形辐射,通过级联同步的方式保证全局多A机房的数据一致性.
比如图中B和C之前的一致性同步,需要通过主站点A来保证.

2.2.2 自定义数据同步(自 由 门)

主要功能是在不修改原始表数据的前提下,触发一下数据表中的数据同步。

可用于:

  • 同步数据订正
  • 全量数据同步. (自 由 门触发全量,同时otter增量同步,需要配置为行记录模式,避免update时因目标库不存在记录而丢失update操作)
    主要原理:

a. 基于otter系统表retl_buffer,插入特定的数据,包含需要同步的表名,pk信息。

b. otter系统感知后会根据表名和pk提取对应的数据(整行记录),和正常的增量同步一起同步到目标库。

目前otter系统感知的自 由 门数据方式为:

  • 日志记录. (插入表数据的每次变更,需要开启binlog,otter获取binlog数据,提取同步的表名,pk信息,然后回表查询整行记录)
    retl_buffer表结构:
CREATE TABLE retl_buffer 
   (    
    ID BIGINT AUTO_INCREMENT,   ## 无意义,自增即可
    TABLE_ID INT(11) NOT NULL,   ## tableId, 可通过该链接查询:http://otter.alibaba-inc.com/data_media_list.htm,即序号这一列,如果配置的是正则,需要指定full_name,当前table_id设置为0. 
    FULL_NAME varchar(512),  ## schemaName + '.' +  tableName  (如果明确指定了table_id,可以不用指定full_name)
    TYPE CHAR(1) NOT NULL,   ## I/U/D ,分别对应于insert/update/delete
    PK_DATA VARCHAR(256) NOT NULL, ## 多个pk之间使用char(1)进行分隔
    GMT_CREATE TIMESTAMP NOT NULL, ## 无意义,系统时间即可
    GMT_MODIFIED TIMESTAMP NOT NULL,  ## 无意义,系统时间即可
    CONSTRAINT RETL_BUFFER_ID PRIMARY KEY (ID) 
   )  ENGINE=InnoDB DEFAULT CHARSET=utf8;

全量同步操作示例:

insert into retl.retl_buffer(ID,TABLE_ID,
FULL_NAME,TYPE,PK_DATA,GMT_CREATE,GMT_MODIFIED)
(select null,0,'$schema.table$','I',id,now(),now
() from $schema.table$);

如果针对多主键时,对应的PK_DATA需要将需要同步表几个主键按照(char)1进行拼接,比如 concat(id,char(1),name)

2.3 具体参数详解

2.3.1 channel参数

  1. 同步一致性. ==> 基于数据库反查(根据binlog反查数据库),基于当前变更(binlog数据)。针对数据库反查,在延迟比较大时比较有效,可将最新的版本快速同步到目标,但会对源库有压力.
  2. 同步模式. ==> 行模式,列模式。行模式特点:如果目标库不存在记录时,执行插入。列模式主要是变更哪个字段,只会单独修改该字段,在双A同步时,为减少数据冲突,建议选择列模式。
  3. 是否开启数据一致性. ==> 请查看数据一致性文档:Otter数据一致性
    a. 数据一致性算法
    b. 一致性反查数据库延迟阀值

2.3.2 pipeline参数

  1. 并行度. ==> 查看文档:Otter调度模型,主要是并行化调度参数.(滑动窗口大小)
  2. 数据反查线程数. ==> 如果选择了同步一致性为反查数据库,在反查数据库时的并发线程数大小
  3. 数据载入线程数. ==> 在目标库执行并行载入算法时并发线程数大小
  4. 文件载入线程数. ==> 数据带文件同步时处理的并发线程数大小
  5. 主站点. ==> 双A同步中的主站点设置
  6. 消费批次大小. ==> 获取canal数据的batchSize参数
  7. 获取批次超时时间. ==> 获取canal数据的timeout参数
    pipeline 高级设置
  • 使用batch. ==> 是否使用jdbc batch提升效率,部分分布式数据库系统不一定支持batch协议
  • 跳过load异常. ==> 比如同步时出现目标库主键冲突,开启该参数后,可跳过数据库执行异常
  • 仲裁器调度模式. ==> 查看文档:Otter调度模型
  • 负载均衡算法. ==> 查看文档:Otter调度模型
  • 传输模式. ==> 多个node节点之间的传输方式,RPC或HTTP. HTTP主要就是使用aria2c,如果测试环境不装aria2c,可强制选择为RPC
  • 记录selector日志. ==> 是否记录简单的canal抓取binlog的情况
  • 记录selector详细日志. ==> 是否记录canal抓取binlog的数据详细内容
  • 记录load日志. ==> 是否记录otter同步数据详细内容
  • dryRun模式. ==> 只记录load日志,不执行真实同步到数据库的操作
  • 支持ddl同步. ==> 是否同步ddl语句
  • 是否跳过ddl异常. ==> 同步ddl出错时,是否自动跳过
  • 文件重复同步对比 ==> 数据带文件同步时,是否需要对比源和目标库的文件信息,如果文件无变化,则不同步,减少网络传输量.
  • 文件传输加密 ==> 基于HTTP协议传输时,对应文件数据是否需要做加密处理
  • 启用公网同步 ==> 每个node节点都会定义一个外部ip信息,如果启用公网同步,同步时数据传递会依赖外部ip.
  • 跳过自 由 门数据 ==> 自定义数据同步的内容
  • 跳过反查无记录数据 ==> 反查记录不存在时,是否需要进行忽略处理,不建议开启.
  • 启用数据表类型转化 ==> 源库和目标库的字段类型不匹配时,开启改功能,可自动进行字段类型转化
  • 兼容字段新增同步 ==> 同步过程中,源库新增了一个字段(必须无默认值),而目标库还未增加,是否需要兼容处理
  • 自定义同步标记 ==> 级联同步中屏蔽同步的功能.

2.3.3 Canal参数

  1. 数据源信息:
    单库配置: 10.20.144.34:3306;
    多库合并配置: 10.20.144.34:3306,10.20.144.35:3306; (逗号分隔)
    主备库配置:10.20.144.34:3306;10.20.144.34:3307; (分号分隔)
  2. 数据库帐号
  3. 数据库密码
  4. connectionCharset ==> 获取binlog时指定的编码
  5. 位点自定义设置 ==> 格式:{"journalName":"","position":0,"timestamp":0};
    指定位置:{"journalName":"","position":0};
    指定时间:{"timestamp":0};
  6. 内存存储batch获取模式 ==> MEMSIZE/ITEMSIZE,前者为内存控制,后者为数量控制.  针对MEMSIZE模式的内存大小计算 = 记录数 * 记录单元大小
  7. 内存存储buffer记录数
  8. 内存存储buffer记录单元大小
  9. HA机制
  10. 心跳SQL配置 ==> 可配置对应心跳SQL,如果配置 是否启用心跳HA,当心跳SQL检测失败后,canal就会自动进行主备切换.

2.3.4 Node参数

  1. 机器名称 ==> 自定义名称,方便记忆
  2. 机器ip ==> 机器外部可访问的ip,不能选择127.0.0.1
  3. 机器端口 ==> 和manager/node之间RPC通讯的端口
  4. 下载端口 ==> 和node之间HTTP通讯的端口
  5. 外部Ip ==> node机器可以指定多IP,通过pipeline配置决定是否启用
  6. zookeeper集群 ==> 就近选择zookeeper集群

2.3.5 Zookeeper集群参数

  1. 集群名字 ==> 自定义名称,方便记忆
  2. zookeeper集群 ==> zookeeper集群机器列表,逗号分隔,最后以分号结束

3.6 主备配置参数

  1. group Key ==> 自定义名称,otter其他地方基于该名称进行引用
  2. master / slave ==> 主备库ip信息
    生成了groupKey,1. 可以在数据库配置时,设置url:jdbc:mysql://groupKey=key (更改 key). 2. 在canal配置时,选择HA机制为media,可填入该groupKey进行引用

deep

3. Manager使用介绍

3.1 背景

otter4.0发布至今也差不多有近一年的时间,中间过程有着比较曲折经历,拥抱了许多变化,目前otter4已经在逐步替换otter3,继续服务icbu的相关中美同步业务,otter3即将成为过去式。

3.2 otter4管理系统(manager)

比如我们内部系统使用了otter.alibaba-inc.com的域名,后续文档描述的时候会基于此域名链接

3.2.1 系统登录

匿名访问时只拥有同步状态的查询权限,可考虑与自己用户授权管理.

3.2.2 同步管理

image

3.2.3 同步模式配置

image

说明:

a. 同步一致性

  1. 基于数据库反查 (简单点说,就是强制反查数据库,从binlog中拿到pk,直接反查对应数据库记录进行同步,回退到几天前binlog进行消费时避免同步老版本的数据时可采用)

  2. 基于当前日志变更 (基于binlog/redolog解析出来的字段变更值进行同步,不做数据库反查,推荐使用)
    b. 同步模式

  3. 行模式 (兼容otter3的处理方案,改变记录中的任何一个字段,触发整行记录的数据同步,在目标库执行merge sql)

  4. 列模式 (基于log中的具体变更字段,按需同步)
    c. 特殊组合: (同样支持)

  5. 基于数据库反查+列模式

  6. 基于当前日志变更+行模式

3.2.4 同步简要信息

image

说明:

  • 延迟时间 = 数据库同步到目标库成功时间 - 数据库源库产生变更时间, 单位秒. (由对应node节点定时推送配置)
  • 最后同步时间 = 数据库同步到目标库最近一次的成功时间 (当前同步关注的相关表,同步到目标库的最后一次成功时间)
  • 最后位点时间 = 数据binlog消费最后一次更新位点的时间 (和同步时间区别:一个数据库可能存在别的表的变更,不会触发同步时间变更,但会触发位点时间变更)

3.2.5同步详细信息

目前主要分为几类:

  1. 映射关系列表
  2. 延迟时间
  3. 同步进度
  4. 监控管理
  5. 日志记录映射关系列表
    image

点击查看打开映射关系信息页面:

image

说明:

  • 定义同步的源和目标的表信息 (注意:表明可以不同,可以定义数据库分库/分表)

  • Push权重 (对应的数字越大,同步会越后面得到同步,优先同步权重小的数据)

  • FileResolver (数据关联文件的解析类,目前支持动态源码推送,在目标jvm里动态编译生效,不再需要起停同步任务)

  • EventProcessor (业务自定义的数据处理类,比如可以定义不需要同步status='ENABLE'的记录或者根据业务改变同步的字段信息 简单业务扩展,otter4新特性)

  • 字段同步 (定义源和目标的字段映射,字段名和字段类型均可进行映射定义,类似于数据库视图定义功能 otter4新特性)

  • 组合同步 (字段组的概念,字段组中的一个字段发生变更,会确保字段组中的3个字段一起同步到目标库 otter4新特性)

  • 多个字段决定一个图片地址,变更文件字段中的任何一个字段,就会触发FileResolver类解析,从而可以确保基于字段同步模式,也可以保证FileResolver能够正常解析出文件 otter4重要的优化)吞吐量

    image

    说明:
  • 数据记录统计 (insert/update/delete的变更总和,不区分具体的表,按表纬度的数据统计,可查看映射关系列表->每个映射关系右边的行为曲线链接)

  • 文件记录统计延迟时间

    image

    说明:
  • 延迟时间的统计 = 数据库同步到目标库成功时间 - 数据库源库产生变更时间, 单位秒. (由对应node节点定时推送配置)同步进度

    image

    说明:
  • mainstem状态: 代表canal模块当前的运行节点(也即是binlog解析的运行节点,解析会相对耗jvm内存)

  • position状态: 当前同步成功的最后binlog位点信息 (包含链接的是数据库ip/port,对应binlog的位置,对应binlog的变更时间此时间即是计算延迟时间的源库变更时间)

  • 同步进度: 每个同步批次会有一个唯一标识,可根据该唯一标示进行数据定位,可以查看每个批次的运行时间,找出性能瓶颈点监控管理

    监控管理.png

说明:

1.监控项目

  • 同步延迟,position超时(位点超过多少时间没有更新) , 一般业务方关心这些即可
  • 异常 (同步运行过程中出现的异常,比如oracle DBA关心oracle系统ORA-的异常信息,mysql DBA关心mysql数据库相关异常)
  • process超时(一个批次数据执行超过多少时间),同步时间超时(数据超过多少时间没有同步成功过)

2.阀值设置

1800@09:00-18:00 , 这例子是指定了早上9点到下午6点,报警阀值为1800.

3.发送对象

otterteam为otter团队的标识,阿里内部使用了dragoon系统监控报警通知,如果外部系统可实现自己的报警通知机制日志记录

image

说明:

  1. 日志标题即为对应的监控规则定义的名字,可根据监控规则检索对应的日志记录
  2. 日志内容即为发送报警的信息
    注意: otter4采用主动推送报警的模式,可以保证报警的及时性以及日志完整性(相比于日志文件扫描机制来说)

3.2.6 配置管理

数据源

image

说明:

  • 主要是数据库连接信息:定义字符编码,ip地址等 (类似napoli等存储也可以抽象为数据源进行配置)

  • 切换数据库时,可根据ip检索同步数据库,找到需要切换的同步任务数据表

    image

    说明:
  • 数据表是一种抽象概念,(针对数据库类型即为一个数据库表的定义)canal配置
    说明:主要是管理canal链接到mysql/oracle获取日志的相关参数等,业务方可不重点关注

机器管理

image

映射规则配置

1.背景

因为alibaba的特殊业务,比如:

  1. 同步数据同时,需要同步数据关联的文件 (需要做数据join)
  2. 同步会员数据,敏感字段信息不能同步到美国站点. (需要做数据过滤)
  3. 两地机房的数据库可能为异构数据库,(需要做字段类型,名字等转化.)
    为解决这些业务,otter引入了映射规则这一概念,用于描述这样的一种同步业务的关系,其粒度可以精确到一张表,或者是一整个库.

2.映射规则

2.1 表映射

otter中每个pipeline可以设置多个映射规则,每个映射规则描述一个数据库同步的内容,比如源表是哪张,同步到哪张目标表。

image

2.1.1 权重的概念

可以先看下:Otter数据入库算法 , 因为otter采用了pk hash的并行载入算法,会将原先binlog中的事务进行打散做并行处理提升同步性能。原先事务被拆散后,通过这个权重概念,来提供“业务上类事务功能".

举个实际点的例子来看:

  • 比如有两张表,product(记录产品的属性信息)和product_detail(记录产品的详情信息),product_detail上有个字段为product_id与product进行关联. 目前为1:1的关系
  • 业务上插入数据可以通过事务,先插入product,然后插入product_detail,最后一起提交到数据库. 正常,页面上通过查询用户的product表的数据,发现有产品记录,然后通过product_id去查询product_detail表,查到后才显示产品页面
  • 假如同步到目标库后,打散事务后,同步过程如果先插入了product表,后插入product_detail表,这时如果有用户访问该产品记录,可能就会遇到product_detail不存在的情况,从而导致页面出错.
  • 所以,我们通过权重定义,比如将product_detail权重定义为5,将product定义为10。 otter会优先同步权重低的表数据,最终可以保证查询product有数据后,product_detail一定有数据,避免业务出错.

2.2 视图映射

如何进入视图编辑:

image

点击下一步后,进入视图编辑页面:

image

说明:

  • 映射规则配置页面,可以选择视图模式为:include或exclude,代表正向匹配或者逆向排除.
  • 视图配置页面,只支持存在的数据表(因为要获取数据表结构,所以.*等正则的数据表不支持配置该功能)
  • 视图配置列表,左右选中列表会按照顺序进行对应,做映射时需按照顺序进行选择.
    举个例子:

如果要排除表字段A的同步,则只需要选择为exclude模式,然后视图编辑页面选择左右皆选择A字段即可,点击保存.

2.3 字段组映射

首先解释一下,需要字段组同步的需求.

  1. 文件同步. 一条记录对应的图片,可能会有一个或者多个字段,比如会有image_path,image_version来决定图片,所以我们可以定义这两个字段为一组,只要满足组内任意一个字段的变更,就会认为需要文件同步.
  2. 数据上的组同步,比如国家,省份,城市,可能在数据库为三个字段. 如果是双A同步,两地同时修改这些字段,但业务上可能在A地修改了国家为美国,在B地修改为省份为浙江,然后一同步,最终就会变成美国,浙江这样的情况. 这种情况可以通过group来解决,将国家,省份,城市做一个group,组内任何一个字段发生了变更,其余字段会做为整体一起变更.
    再来看一下配置:(点击视图编辑页面的下一步,即可进入)

    image

说明:也可不配置视图,单独配置字段组,此时可选择的字段即为当前所有字段(映射规则按照同名映射).

3.高级映射

主要分为两类:

  1. 文件同步
  2. 自定义数据同步
    具体代码扩展方式和配置可参见: Otter扩展性

配置方式:

image

3.1 文件同步

首先解释一下文件同步的需求,阿里巴巴国际站业务,主要模式为对外贸易,卖家基本在国内,买家在国外. 所以,目前我们的机房部署为杭州和美国各一个,卖家访问杭州机房,买家访问美国机房。卖家在国内发布产品和图片,通过otter同步到美国,同步产品数据记录的同时,同样需要把图片同步过去,保证买家用户的访问体验. 所以,基于这个业务场景,衍生出了文件同步的需求.

所以,做文件同步的几个前提:

  1. 异地同步 (需要部署为两个node,S/E和T/L分为两地. )
  2. 数据触发文件同步 (数据库记录做为类似文件索引信息,不支持单独同步文件)
  3. 本地文件同步 (需要同步的文件需要和node部署在一台机器上或者通过nfs mount,如果要同步 公司自带的分布式文件系统的数据,otter需要做额外扩展)

文件同步准备工作:

  1. 准备两台机器,分别部署上两个node
  2. 配置channel/pipeline同步,配置映射规则
  3. 编写FileResolver解析类,根据binlog中的变更数据,转化为文件的路径信息. 例子:TestFileResolver
public class TestFileResolver extends AbstractFileResolver {
public FileInfo[] getFileInfo(Map&lt;String, String&gt; rowMap) {
    // 基本步骤:
    // 1. 获取binlog中的变更字段,比如组成文件有多个字段组成version+path
    // 2. 基于字段内容,构造一个文件路径,目前开源版本只支持本地文件的同步.(如果是网络文件,建议进行NFS mount到ndde机器).
    // 3. 返回FileInfo数组,(目前不支持目录同步,如果是目录需要展开为多个FileInfo的子文件),如果不需要同步,则返回null.
    String path = rowMap.get("FIELD"); //注意为大写
    FileInfo fileInfo = null;
    if (StringUtils.isNotEmpty(path)) {
        fileInfo = new FileInfo(path);
        return new FileInfo[] { fileInfo };
    } else {
        return null;
    }
}

}

3.2 自定义数据同步

通过前面的字段视图映射,或许可以解决80%的需求,但总会有一小撮的特殊用户,希望可以自定义自己的同步数据内容,所以otter引入了自定义数据同步为EventProcessor,允许你任意改变整个同步过程中的数据内容.

可以支持的需求:

  1. 根据字段内容,判断是否需要屏蔽本记录同步

  2. 动态增加/减少字段

  3. 动态修改字段内容

  4. 动态改变事件类型(Insert/Update/Delete)
    几点注意:

  5. EventProcessor主要是在E模块进行数据处理,也就是EventProcessor处理后的数据,会再次经过视图配置,字段组映射,文件同步,最后进入Transform处理.

  6. EventProcessor修改数据中的schema/table name需要谨慎,因为会继续后续的E/T/L流程,所以需要保证修改后的name在映射规则列表里有配置,否则同步会出错.
    一个例子:(比如我想将源库的每条binlog变更,记录到一个日志表binlog,映射规则配置为.*所有表的同步)

代码:TestEventProcessor

public class TestEventProcessor extends AbstractEventProcessor {
public boolean process(EventData eventData) {
    // 基本步骤:
    // 1. 获取binlog中的变更字段
    // 2. 根据业务逻辑进行判断,如果需要忽略本条数据同步,直接返回false,否则返回true
    // 3. 根据业务逻辑进行逻辑转化,比如可以修改整个EventData数据.  

    // 本文例子:源库的每条binlog变更,记录到一个日志表binlog
    // create table test.binlog(
    //        id bigint(20) auto_increment,
    //        oschema varchar(256),
    //        otable varchar(256),
    //        gtime varchar(32)
    //        ovalue text,
    //        primary key(id);
    //    )
    // 在process处理中,可以修改EventData的任何数据,达到数据转换的效果, just have fun.
    JSONObject col = new JSONObject();
    JSONArray array = new JSONArray();
    for (EventColumn column : eventData.getColumns()) {
        JSONObject obj = this.doColumn(column);
        array.add(obj);
    }

    for (EventColumn key : eventData.getKeys()) {
        JSONObject obj = this.doColumn(key);
        array.add(obj);
    }
    // 记录原始的表信息
    col.put("schema", eventData.getSchemaName());
    col.put("table", eventData.getTableName());
    col.put("columns", array);
    col.put("dml", eventData.getEventType());
    col.put("exectime", eventData.getExecuteTime());

    // 构造新的主键
    EventColumn id = new EventColumn();
    id.setColumnValue(eventData.getSchemaName());
    id.setColumnType(Types.BIGINT);
    id.setColumnName("id");
    // 构造新的字段
    EventColumn schema = new EventColumn();
    schema.setColumnValue(eventData.getSchemaName());
    schema.setColumnType(Types.VARCHAR);
    schema.setColumnName("oschema");

    EventColumn table = new EventColumn();
    table.setColumnValue(eventData.getTableName());
    table.setColumnType(Types.VARCHAR);
    table.setColumnName("otable");

    EventColumn ovalue = new EventColumn();
    ovalue.setColumnValue(col.toJSONString());
    ovalue.setColumnType(Types.VARCHAR);
    ovalue.setColumnName("ovalue");

    EventColumn gtime = new EventColumn();
    gtime.setColumnValue(eventData.getExecuteTime() + "");
    gtime.setColumnType(Types.VARCHAR);
    gtime.setColumnName("gtime");

    // 替换为新的字段和主键信息
    List&lt;EventColumn&gt; cols = new ArrayList&lt;EventColumn&gt;();
    cols.add(schema);
    cols.add(table);
    cols.add(gtime);
    cols.add(ovalue);
    eventData.setColumns(cols);

    List&lt;EventColumn&gt; keys = new ArrayList&lt;EventColumn&gt;();
    keys.add(id);
    eventData.setKeys(keys);

    //修改数据meta信息
    eventData.setEventType(EventType.INSERT);
    eventData.setSchemaName("test");
    eventData.setTableName("binlog");
    return true;
}

private JSONObject doColumn(EventColumn column) {
    JSONObject obj = new JSONObject();
    obj.put("name", column.getColumnName());
    obj.put("update", column.isUpdate());
    obj.put("key", column.isKey());
    if (column.getColumnType() != Types.BLOB &amp;&amp; column.getColumnType() != Types.CLOB) {
        obj.put("value", column.getColumnValue());
    } else {
        obj.put("value", "");
    }
    return obj;
}

}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值