项目地址:https://github.com/alibaba/otter/
名称:otter ['ɒtə(r)]
译意: 水獭,数据搬运工
语言: 纯java开发
定位: 基于数据库增量日志解析,准实时同步到本机房或异地机房的mysql/oracle数据库. 一个分布式数据库同步系统
db : 数据源以及需要同步到的库
Canal : 获取数据库增量日志,canal支持独立部署和内嵌使用两种模式。otter使用canal的内嵌方法获取数据库增量日志
manager : 配置同步规则设置数据源同步源等
zookeeper : 协调node进行协调工作
node : 负责任务处理,即根据任务配置对数据源进行解析并同步到目标数据库的操作
原理描述:
基于Canal开源产品,获取数据库增量日志数据。
典型管理系统架构,manager(web管理)+node(工作节点)
a. manager运行时推送同步配置到node节点
b. node节点将同步状态反馈到manager上
基于zookeeper,解决分布式状态调度的,允许多node节点之间协同工作
镜像canal/canal-server包含了otter所依赖的所有组件,如mysql、zookeeper、manager、node,几个组件的互相依赖的配置都已经初始化完成
拉取镜像
docker pull canal/canal-server
启动otter
创建并进入工作目录,使用otter工程自带的run.sh脚本,会处理好host参数、端口映射、目录挂载等工作
[root@administrator otter]# curl -fsSL https://raw.githubusercontent.com/alibaba/otter/master/docker/run.sh | bash
docker run -d -it -h 152.25.4.21 --name=otter-all -v /usr/local/program/otter/data/mysql:/var/lib/mysql -v /usr/local/program/otter/data/zkData:/home/admin/zkData --net=host -p 8080:8080 -p 8081:8081 -p 2181:2181 -p 2088:2088 -p 2089:2089 -p 2090:2090 -m 4096m canal/otter-all
云服务器使用Docker安装Otter默认绑定内网IP,导致外网IP无法正常使用,不清楚如何修改,放弃该方式。
整个otter架构依赖了zookeeper进行多节点调度,所以需要安装zookeeper,不需要初始化节点,otter程序启动后会自检。 manager需要在otter.properties中指定一个就近的zookeeper集群机器
拉取镜像
docker pull zookeeper
启动容器
docker run -id --name zk -p 2181:2181 -v /etc/localtime:/etc/localtime zookeeper:latest
查看容器日志
docker logs -f zk
使用otter进行数据同步时,需要三类数据库
源数据库
目标数据库
otter配置数据库
mkdir mysql1
# 创建MySQL数据库配置文件目录,数据存放目录
cd mysql1
mkdir conf data
# 创建MySQL数据库配置文件
cd conf
vim mysql.cnf
[mysql1]
server_id=1
binlog_format=row
log-bin=mysql-bin
character-set-server=utf8
collation-server=utf8_general_ci
# 创建并启动MySQL
docker run -id --name mysql1 \
-v $PWD/data:/var/lib/mysql \
-v $PWD/conf:/etc/mysql/conf.d \
-p 3306:3306 \
-e MYSQL_ROOT_PASSWORD=123456 mysql:5.7
mkdir mysql2
# 创建MySQL数据库配置文件目录,数据存放目录
cd mysql2
mkdir conf data
# 创建MySQL数据库配置文件
cd conf
vim mysql.cnf
[mysql2]
server_id=2
binlog_format=row
log-bin=mysql-bin
character-set-server=utf8
collation-server=utf8_general_ci
# 创建并启动MySQL
docker run -id --name mysql2 \
-v $PWD/data:/var/lib/mysql \
-v $PWD/conf:/etc/mysql/conf.d \
-p 3307:3306 \
-e MYSQL_ROOT_PASSWORD=123456 mysql:5.7
otter manager依赖于mysql进行配置信息的存储,所以需要安装mysql,并初始化otter manager的系统表结构
mkdir mysql3
# 创建MySQL数据库配置文件目录,数据存放目录
cd mysql3
mkdir conf data
# 创建MySQL数据库配置文件
cd conf
vim mysql.cnf
[mysql3]
server_id=3
binlog_format=row
log-bin=mysql-bin
character-set-server=utf8
collation-server=utf8_general_ci
# 创建并启动MySQL
docker run -id --name mysql3 \
-v $PWD/data:/var/lib/mysql \
-v $PWD/conf:/etc/mysql/conf.d \
-p 3308:3306 \
-e MYSQL_ROOT_PASSWORD=123456 mysql:5.7
创建名为otter
的数据库,并创建相应数据表
下载otter数据库文件并在mysql命令行中执行sql脚本进行建表
wget https://github.com/alibaba/otter/blob/master/manager/deployer/src/main/resources/sql/otter-manager-schema.sql
source /root/otter-manager-schema.sql;
下载manager
和node
:https://github.com/alibaba/otter/releases
https://ghproxy.com/https://github.com/alibaba/otter/releases/download/otter-4.2.18/manager.deployer-4.2.18.tar.gz
https://ghproxy.com/https://github.com/alibaba/otter/releases/download/otter-4.2.18/node.deployer-4.2.18.tar.gz
解压manager
mkdir manager
tar -zxf manager.deployer-4.2.18.tar.gz -C manager
修改otter manager配置文件
vim ./manager/conf/otter.properties
## otter manager domain name
## 修改Ip
otter.domainName = IP
## otter manager http port
## manager控制台端口
otter.port = 8080
## jetty web config xml
otter.jetty = jetty.xml
## otter manager database config
## 修改数据库配置信息
otter.database.driver.class.name = com.mysql.jdbc.Driver
otter.database.driver.url = jdbc:mysql://IP:3308/otter?autoReconnect=true&useSSL=false
otter.database.driver.username = root
otter.database.driver.password = 123456
## otter communication port
## 通信端口
otter.communication.manager.port = 1099
## otter communication payload size (default = 8388608)
otter.communication.payload = 8388608
## otter communication pool size
otter.communication.pool.size = 10
## default zookeeper address
## 修改zookeeper地址
otter.zookeeper.cluster.default = IP:2181
## default zookeeper sesstion timeout = 60s
otter.zookeeper.sessionTimeout = 60000
## otter arbitrate connect manager config
otter.manager.address = ${otter.domainName}:${otter.communication.manager.port}
## should run in product mode , true/false
otter.manager.productionMode = true
## self-monitor enable or disable
otter.manager.monitor.self.enable = true
## self-montir interval , default 120s
otter.manager.monitor.self.interval = 120
## auto-recovery paused enable or disable
otter.manager.monitor.recovery.paused = true
# manager email user config
otter.manager.monitor.email.host = smtp.gmail.com
otter.manager.monitor.email.username =
otter.manager.monitor.email.password =
otter.manager.monitor.email.stmp.port = 465
启动otter manager
./manager/bin/startup.sh
查看日志
tail -60f ./manager/logs/manager.log
otter node会受otter manager的管理,所以需要先安装otter manager
解压node.deployer-4.2.18.tar.gz到node目录中
tar -zxvf node.deployer-4.2.18.tar.gz -C node
修改Otter Node配置文件
vim ./node/conf/otter.properties
# otter node root dir
otter.nodeHome = ${user.dir}/../
## otter node dir
otter.htdocs.dir = ${otter.nodeHome}/htdocs
otter.download.dir = ${otter.nodeHome}/download
otter.extend.dir= ${otter.nodeHome}/extend
## default zookeeper sesstion timeout = 60s
otter.zookeeper.sessionTimeout = 60000
## otter communication payload size (default = 8388608)
otter.communication.payload = 8388608
## otter communication pool size
otter.communication.pool.size = 10
## otter arbitrate & node connect manager config
## 修改Otter Manager的IP与通信端口
otter.manager.address = IP:1099
启动node
./node/bin/startup.sh
查看日志
tail -60f ./node/logs/node/node.log
node节点进行跨机房传输时,会使用到HTTP多线程传输技术,目前主要依赖了aria2c做为其下载客户端
aria2 官方首页:http://aria2.sourceforge.net/
下载页面: http://sourceforge.net/projects/aria2/files/stable/
注意:下载完成或者编译完成后,将对应的aria2c包加入到PATH路径即可
yum -y install epel-release aria2
查看是否安装成功
[root@administrator ~]# aria2c -v
aria2 版本 1.34.0
Copyright (C) 2006, 2017 Tatsuhiro Tsujikawa
在manager页面为node定义配置信息,并生一个唯一id
机器名称:可以随意定义,方便自己记忆即可
机器ip:对应node节点将要部署的机器ip,如果有多ip时,可选择其中一个ip进行暴露. (此ip是整个集群通讯的入口,实际情况千万别使用127.0.0.1,否则多个机器的node节点会无法识别)
机器端口:对应node节点将要部署时启动的数据通讯端口,建议值:2088
下载端口:对应node节点将要部署时启动的数据下载端口,建议值:9090
外部ip :对应node节点将要部署的机器ip,存在的一个外部ip,允许通讯的时候走公网处理
zookeeper集群:为提升通讯效率,不同机房的机器可选择就近的zookeeper集群
机器添加完成后,跳转到机器列表页面,获取对应的机器序号nid(这里指序号1)
获取到node节点对应的唯一标示,称之为node id,简称:nid. 记录该nid,后续启动nid时会使用
将添加机器后获取到的序号,保存到conf目录下的nid文件,如添加的机器对应序号为1
echo 1 > conf/nid
多种同步方式配置,这里以单向同步为例,更多配置参考官方文档
单向同步
双向同步
双A同步
级联同步
多A同步
自定义数据同步
分别在源数据库(mysql1:3306)和目标数据库(mysql2:3307)创建demo
数据库,并分别创建test
表
CREATE TABLE `test` (
`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(id,name) values(null,'hello');
遇到异常1:
抱歉,数据库未通过验证,请检查相关配置!
查看manager日志
Caused by: javax.net.ssl.SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate)
修改jdk/jre/lib/security/java.security文件,需要删除掉SSLv3, TLSv1, TLSv1.1然后重启项目
# jdk.tls.disabledAlgorithms=SSLv3, TLSv1, TLSv1.1, RC4, DES, MD5withRSA, \
jdk.tls.disabledAlgorithms= RC4, DES, MD5withRSA, \
DH keySize < 1024, EC keySize < 224, 3DES_EDE_CBC, anon, NULL, \
include jdk.disabled.namedCurves
character-set-server=utf8
collation-server=utf8_general_ci
数据库地址:指源库的ip和端口
connectionCharset ==> 获取binlog时指定的编码
位点自定义设置 ==> 格式:{“journalName”:"",“position”:0,“timestamp”:0};
指定位置:{“journalName”:"",“position”:0};
指定时间:{“timestamp”:0};
内存存储batch获取模式 ==> MEMSIZE/ITEMSIZE,前者为内存控制,后者为数量控制. 针对MEMSIZE模式的内存大小计算 = 记录数 * 记录单元大小
内存存储buffer记录数
内存存储buffer记录单元大小
心跳SQL配置 ==> 可配置对应心跳SQL,如果配置 是否启用心跳HA,当心跳SQL检测失败后,canal就会自动进行主备切换.
基于数据库反查 (简单点说,就是强制反查数据库,从binlog中拿到pk,直接反查对应数据库记录进行同步,回退到几天前binlog进行消费时避免同步老版本的数据时可采用)
基于当前日志变更 (基于binlog/redolog解析出来的字段变更值进行同步,不做数据库反查,推荐使用)
同步模式
行模式 (兼容otter3的处理方案,改变记录中的任何一个字段,触发整行记录的数据同步,在目标库执行merge sql)
列模式 (基于log中的具体变更字段,按需同步)
特殊组合: (同样支持)
基于数据库反查+列模式
基于当前日志变更+行模式
延迟时间 = 数据库同步到目标库成功时间 - 数据库源库产生变更时间, 单位秒. (由对应node节点定时推送配置)
最后同步时间 = 数据库同步到目标库最近一次的成功时间 (当前同步关注的相关表,同步到目标库的最后一次成功时间)
最后位点时间 = 数据binlog消费最后一次更新位点的时间 (和同步时间区别:一个数据库可能存在别的表的变更,不会触发同步时间变更,但会触发位点时间变更)
Caused by: com.alibaba.dubbo.remoting.RemotingException: client(url: dubbo://IP:2088/endpoint?acceptEvent.timeout=50000&client=netty&codec=dubbo&connections=30&heartbeat=60000&iothreads=4&lazy=true&payload=8388608&send.reconnect=true&serialization=java&threads=50) failed to connect to server /IP:2088, error message is:connection timed out
解决:
首先云厂商端口已开放,折腾很久,最后发现由于使用了宝塔,被宝塔把端口限制了,开放端口即可。很纳闷有的端口在云厂商那儿开放后无需在宝塔开放端口即可使用。