1.首先mysql要開啟binlog瓤湘,并配置為row格式?
[mysqld]
log-bin=mysql-bin # 開啟 binlog
binlog-format=ROW # 選擇 ROW 模式
server_id=1 # 配置 MySQL replaction 需要定義,不要和 canal 的 slaveId 重復(fù)
2.為Canal創(chuàng)建用戶并授權(quán)?
CREATE USER canal IDENTIFIED BY 'canal';
grant select,replication slave,replication client on *.* to? 'canal' @ '%'? identified by 'canal'? #IP需要修改為Canal節(jié)點(diǎn)所在的信息(這里有個(gè)坑,replication slave 的級(jí)別是global恶座,所以如果想限制用戶只在某一個(gè)數(shù)據(jù)庫下生效,如:grant replication slave on test.* to? 'canal' @ '%' 枚钓, 想讓用戶只在test庫下生效鹅髓,會(huì)報(bào)錯(cuò):Incorrect usage of DB GRANT and GLOBAL PRIVILEGES,所以不能只作用于某一數(shù)據(jù)庫廓八,而是全局奉芦, 如果想以數(shù)據(jù)庫粒度限制,在my.cnf中添加binlog-do-db=test來限制主從復(fù)制的數(shù)據(jù)庫為test)
3.開始部署Canal集群(需要安裝zookeeper剧蹂,此處略)
下載Canal安裝包声功,地址為https://github.com/alibaba/canal,推薦使用1.1.4版本宠叼,該版本引入了canal-admin先巴,可通過WebUI對(duì)Canal進(jìn)行管理?
Canal主要配置文件有2個(gè),一個(gè)是conf/canal.properties冒冬,一個(gè)是conf/example/instance.properties伸蚯。Canal有個(gè)強(qiáng)大的地方,修改完配置文件后不需要重啟服務(wù)简烤,會(huì)自動(dòng)重新加載剂邮。?
a.修改conf/canal.properties,該文件屬于canal全局配置文件横侦,用于配置canal工作模式抗斤、zk與kafka等信息
canal.zkServers = 192.168.94.10:2181,192.168.94.11:2181,192.168.94.12:2181 #zk集群地址
canal.instance.global.spring.xml = classpath:spring/default-instance.xml #默認(rèn)的file-instance不支持HA持久化,需要修改為default
b.修改conf/example/instance.properties丈咐。這是每個(gè)Canal實(shí)例的配置文件,里面配置了需要同步的數(shù)據(jù)庫信息龙宏、mq信息等。instance.properties文件所屬的目錄就屬于一個(gè)實(shí)例,canal默認(rèn)已創(chuàng)建好一個(gè)名為example的示范實(shí)例沸停,如果要同步多個(gè)數(shù)據(jù)庫實(shí)例的話良狈,復(fù)制example目錄后修改instance.properties即可。?
canal.instance.mysql.slaveId=2131 #ID不可與主庫和其他從庫重復(fù)
# position info? 需要同步的數(shù)據(jù)庫信息
canal.instance.master.address=192.168.10.56:3306
canal.instance.dbUsername=canal #canal在數(shù)據(jù)庫中的用戶
canal.instance.dbPassword=canal? #canal用戶的密碼
-------------------------------------------------------------------------------------------------------
最后記得要修改配置文件中的各種端口黍特,修改 canal.propeties 文件中的?canal.port蛙讥、canal.metrics.pull.port、canal.admin.jmx.port(這個(gè)我暫時(shí)沒看到) 各配置項(xiàng)灭衷,指向其它端口次慢!
canal.port = 12111
canal.metrics.pull.port = 12112
然后就可啟動(dòng)Canal?
bin/startup.sh? #此啟動(dòng)文件中還有一個(gè)啟動(dòng)端口需修改,否則多個(gè)實(shí)例就會(huì)端口沖突(address=9099(此為startup.bat中的))!迫像!啟動(dòng)后需要觀察2個(gè)日志劈愚,logs/example/example.log和logs/canal/canal.log
啟動(dòng)每Canal節(jié)點(diǎn)后,通過zk客戶端可以查看當(dāng)前正在工作的Canal節(jié)點(diǎn)闻妓。當(dāng)Canal主節(jié)點(diǎn)故障時(shí)菌羽,客戶端能通過zk獲取到另外節(jié)點(diǎn)繼續(xù)工作?
zkcli.sh
[zk: localhost:2181(CONNECTED) 10] get /otter/canal/destinations/example/running
{"active":true,"address":"192.168.255.10:12111"}
[zk: localhost:2181(CONNECTED) 11] ls /otter/canal/destinations/example/cluster
[192.168.255.10:11111, 192.168.255.10:12111]
4.在springboot中,引入canal相關(guān)的包
<dependency>
<groupId>com.alibaba.otter</groupId>
<artifactId>canal.client</artifactId>
<version>1.1.4</version>
</dependency>
<dependency>
<groupId>com.alibaba.otter</groupId>
<artifactId>canal.protocol</artifactId>
<version>1.1.4</version>
</dependency>
<dependency>
<groupId>com.alibaba.otter</groupId>
<artifactId>canal.common</artifactId>
<version>1.1.4</version>
</dependency>
(坑B: <dependency>
<groupId>com.alibaba.otter</groupId>
<artifactId>canal.client</artifactId>
<version>1.1.4</version>
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
</exclusion>
<exclusion>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
</exclusion>
<exclusion>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</exclusion>
</exclusions>
</dependency>
,這幾個(gè)排除的極容易沖突由缆,導(dǎo)致項(xiàng)目起不來)
建立連接(連接地址寫zookeeper即可注祖,后面參數(shù)是instance的名字及連接mysql的用戶名和密碼):
CanalConnectors.newClusterConnector("127.0.0.1:2181","example","canal","canal");
最后就可以去定時(shí)獲取canal同步到的數(shù)據(jù)了。
>Α是晨!有兩個(gè)沒有暫時(shí)還解決的問題:
1.canal客戶端在消費(fèi)server端發(fā)來的binlog變化時(shí),當(dāng)既沒有ack浸卦,也沒有rollback時(shí)署鸡,將程序kill -9關(guān)掉,發(fā)現(xiàn)server端的binlog的position居然更新了限嫌,這導(dǎo)致有可能出現(xiàn)靴庆,es還未同步數(shù)據(jù),程序宕掉了怒医,而消費(fèi)進(jìn)度缺前進(jìn)以至于數(shù)據(jù)丟失的問題(但我反復(fù)測(cè)試后炉抒,在es同步前關(guān)掉程序,發(fā)現(xiàn)server端并未更新pos稚叹,但在最后ack前關(guān)掉程序焰薄,server的pos卻更新了)
2.canal不能同時(shí)多個(gè)client消費(fèi)一個(gè)server,在官網(wǎng)上說的是一個(gè)client消費(fèi)扒袖,另一個(gè)冷備塞茅,但實(shí)際是,一個(gè)在消費(fèi)季率,另一個(gè)在搗亂! 當(dāng)同時(shí)開兩個(gè)client時(shí)野瘦,總有一個(gè)會(huì)被server端返回batchId不存在,即在server的內(nèi)存中batchId被清掉了飒泻,這他媽就導(dǎo)致會(huì)丟數(shù)據(jù)啊鞭光,到底是配置還是要調(diào)整什么在github 的issue上也沒得到回答,項(xiàng)目緊沒時(shí)間去看server端的源碼再來解決問題泞遗,只能擱置惰许,先用kafka來同步吧!
####################################################################
canal還提供了界面ui史辙,canal-admin汹买,首先下載canal.admin-1.1.4.tar.gz佩伤,然后替換它lib目錄下的數(shù)據(jù)庫jar包為mysql-connector-java-8.0.12.jar(現(xiàn)在都用mysql8,它自帶了驅(qū)動(dòng)版本低了)卦睹,然后修改conf里的application.yml 配置文件畦戒,主要就是一些數(shù)據(jù)庫的配置,它需要建立一個(gè)庫(canal_manager)结序,要在mysql中導(dǎo)入它準(zhǔn)備好的數(shù)據(jù)(conf下的canal_manager.sql障斋,source conf/canal_manager.sql),然后啟動(dòng)即可徐鹤,如果界面上登錄報(bào)錯(cuò)垃环,那十九是mysql8密碼加密模式的問題,修改mysql中canal-admin使用的用戶的密碼加密模式:alter user '用戶名'@localhostIDENTIFIED WITH mysql_native_password by '你的密碼';
最后登錄成功后返敬,在界面上的集群管理選擇新建集群遂庄,結(jié)果還他媽報(bào)錯(cuò),Error[Column 'modified_time' cannot be null]劲赠,只好把所有表的這個(gè)字段加上默認(rèn)時(shí)間:
ALTER TABLE canal_manager.canal_node_server
MODIFY modified_time timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP;
ALTER TABLE canal_manager.canal_adapter_config
MODIFY modified_time timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP;
ALTER TABLE canal_manager.canal_cluster
MODIFY modified_time timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP;
ALTER TABLE canal_manager.canal_config
MODIFY modified_time timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP;
ALTER TABLE canal_manager.canal_instance_config
MODIFY modified_time timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP;
ALTER TABLE canal_manager.canal_user
MODIFY creation_date timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP;