一、问题描述:
canal高可用集群我们搭建好了,集群相对来说比较稳定。在实际使用中发生过数据峰值较大、网络带宽不足等原因导致的数据同步延时较大,影响了业务开展。那么咱们有没有办法监控一下cananl的同步进度?
找了一圈,发现并没有现成的组件,只能自己写一个了。
二、实现思路
找到数据时间和同步的进度时间进行比对,就可以得到数据同步的时间差了,然后再将整个流程进行封装就行了。
三、实现过程
1.获取同步的进度信息
咱们使用的是高可用集群,数据同步进度在zookeeper中存储,怎么能获取到同步的进度数据呢?
在zookeeper客户端下,可以使用get命令获取指定路径节点内容。而canal的同步信息存储的路径,以example为例,一般在在/canal/otter/canal/destinations/example/1001/cursor
的路径下
那么我们可以这样获取:
/opt/module/zookeeper/bin/zkCli.sh -server kafka01,kafka02,kafka03:2181 -x get /canal/otter/canal/destinations/example/1001/cursor
结果信息:
{"@type":"com.alibaba.otter.canal.protocol.position.LogPosition","identity":{"slaveId":-1,"sourceAddress":{"address":"rm-XXXXXXXXXXXXXXXXXXXXXX.mysql.rds.aliyuncs.com","port":3306}},"postion":{"gtid":"","included":false,"journalName":"mysql-bin.000586","position":50460257,"serverId":1776724446,"timestamp":1681463140000}}
cZxid = 0x700187c2e
ctime = Fri Apr 07 11:30:00 CST 2023
mZxid = 0x70027057b
mtime = Fri Apr 14 17:05:40 CST 2023
pZxid = 0x700187c2e
cversion = 0
dataVersion = 145380
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 320
numChildren = 0
怎么进一获取json的数据呢?安装 jq 命令行工具
yum -y install jq
再获取
/opt/module/zookeeper/bin/zkCli.sh -server kafka01,kafka02,kafka03:2181 -x get /canal/otter/canal/destinations/example/1001/cursor | grep com.alibaba.otter.canal.protocol.position.LogPosition | jq '.postion.timestamp'
2.存储同步的进度信息
建表
CREATE TABLE `canal_monitor` (
`id` bigint(30) NOT NULL AUTO_INCREMENT,
`dbname` varchar(100) DEFAULT NULL,
`updatetime` varchar(20) DEFAULT NULL,
`canaltime` bigint(20) DEFAULT NULL,
`logposition_info` text,
PRIMARY KEY (`id`) USING BTREE,
KEY `idx_updatetime` (`updatetime`) USING BTREE,
KEY `idx_dbname` (`dbname`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=688226 DEFAULT CHARSET=utf8;
封装脚本,插入同步信息的相关的数据
#!/bin/bash
set -e
mysql_opt() {
db_name=$1
sql_lan=$2
mysql $sql_opt << EOF
USE $db_name -A;
$sql_lan;
QUIT
EOF
}
sql_opt="-hrm-XXXXXXXX.mysql.rds.aliyuncs.com -uuser -p123456 -s"
zookeeper_opt="/opt/module/zookeeper/bin/zkCli.sh -server kafka01,kafka02,kafka03:2181"
mysql_opt canal_alert "
delete from canal_monitor where updatetime<date_format(date_sub(current_date,interval 1 day),'%Y-%m-%d 00:00:00');
insert into canal_monitor(dbname,updatetime,canaltime,logposition_info) select 'example','`date "+%Y-%m-%d %H:%M:%S"`','`${zookeeper_opt} -x get /canal/otter/canal/destinations/example/1001/cursor | grep com.alibaba.otter.canal.protocol.position.LogPosition | jq '.postion.timestamp'`','`${zookeeper_opt} -x get /canal/otter/canal/destinations/example/1001/cursor | grep com.alibaba.otter.canal.protocol.position.LogPosition`' from dual;
"
3.比对同步时间
拿到数据之后,咱们可以进行比对了,查询出时间差大于10分钟的instance
SELECT
a.dbname,
date_format( a.updatetime, '%Y-%m-%d %H:%i:%s' ) updatetime,
date_format( from_unixtime( a.canaltime / 1000 ), '%Y-%m-%d %H:%i:%s' ) canaltime,
TIMESTAMPDIFF(
MINUTE,
from_unixtime( a.canaltime / 1000 ),
a.updatetime
) minute_sub
FROM
canal_monitor a
JOIN (
SELECT
dbname,
max( updatetime ) updatetime
FROM
canal_monitor
GROUP BY
dbname
) b ON a.updatetime = b.updatetime
AND a.dbname = b.dbname
HAVING
minute_sub >= 10
4.封装集成告警平台
最后,咱们可以把整个流程封装成java程序或者shell脚本,在集成钉钉、微信告警就行了,具体方式参考钉钉告警平台等。