前提

Canal上一个正式版是于2019-9-2发布的v1.1.4,笔者几个月前把这个版本的Canal推上了生产环境,部署了HA集群。过程中虽然遇到不少的坑,但是在不出问题的前提下,Canal的作用还是非常明显的。上周的一次改造上线之后,去掉了原来对业务系统订单数据通过RabbitMQ实时推送的依赖,下游的统计服务完全通过上游业务主库的binlog事件进行聚合,从而实现了核心业务和实时统计两个不同的模块解耦。

这篇文章简单分析一下如何搭建生产环境下可靠的Canal高可用集群。

Canal高可用集群架构

CanalHA其实包含了服务端HA和客户端的HA,两者的实现原理差不多,都是通过Zookeeper实例标识某个特定路径下抢占EPHEMERAL(临时)节点的方式进行控制,抢占成功的一者会作为运行节点(状态为running),而抢占失败的一方会作为备用节点(状态是standby)。下文只分析服务端HA集群搭建,因为一般情况下使用内建的数据管道例如Kafka,基本屏蔽了客户端的细节。假设客户端使用了Kafka,也就是Canal从主库同步到的binlog事件最终会投放到Kafka,那么Canal服务端HA集群架构大致如下:

这是全局来看,而一个运行的Canal服务端,可以同时支持监听多个上游数据库的binlog,某个主库解析配置的抽象在Canal中的术语叫做Instance(实例):

定义多个Instance的操作很简单,主配置文件$CANAL_HOME/conf/canal.properties中的canal.destinations配置项通过英文逗号分隔多个标识如:

# canal.destinations=[Instance标识1,Instance标识2...,Instance标识n]
canal.destinations=customer-service,payment-service

然后在$CANAL_HOME/conf目录下添加customer-servicepayment-service文件夹,把原来的$CANAL_HOME/conf/example文件夹中的instance.properties拷贝过去,按需修改里面的配置即可:

$CANAL_HOME
- conf
- customer-service
- instance.properties # 这里主要配置customer-service主库的连接信息、过滤规则和目标topic的配置等等
配置 【canal.mq.topic = customer-service】
- payment-service
- instance.properties # 这里主要配置payment-service主库的连接信息和过滤规则和目标topic的配置等等
配置 【canal.mq.topic = payment-service】

Canal最终解析好的binlog事件会分别以topiccustomer-servicepayment-service发送到Kafka集群中,这样就能确保不同数据源解析出来的binlog不会混乱。

Canal会实时监听每个Instance的配置文件instance.properties的变动,一旦发现配置文件有属性项变更,会进行一次热加载,原则是变更Instance的配置文件是不用重启Canal服务的。

搭建Canal高可用集群

为了简单起见,Zookeeper和Kafka使用单节点作为示例,实际上生产环境中建议Zookeeper或Kafka都使用奇数个(>=3)节点的集群。

笔者本地一台CentOS7.x的虚拟机192.168.56.200上安装了ZookeeperKafka,本地开发机192.168.56.1Windows10操作系统。虚拟机安装了一个MySQL8.x的服务端(Canal要求MySQL服务开启binlog支持特性,并且要求binlog类型为ROW,这两点MySQL8.x是默认开启的),现在详细讲解在这两台机器上搭建一个Canal服务端HA集群。

生产上搭建Canal服务端HA集群的机器最好在同一个内网中,并且建议服务器由Canal独占,不要部署其他中间件或者应用,机器的配置建议4核心8GB内存起步。

下载当前(2020-08-22)最新版本的canal.deployer-1.1.4.tar.gz

拷贝和解压canal.deployer-1.1.4.tar.gz到虚拟机的/data/canal目录下,同时解压一份在本地开发机的磁盘中。演示直接使用example标识的Instance。修改虚拟机/data/canal/conf/example/instance.properties

注意这里笔者把topic设置为和数据库的schema一致。其他细节项就不再进行展开,有兴趣可以看笔者之前写过的一篇文章《基于Canal和Kafka实现MySQL的Binlog近实时同步》,里面很详细地介绍了怎么部署一个可用的Canal单机服务,包括了MySQLZookeeperKafka的安装和使用。

同理,在开发机中的对应的配置文件中添加一模一样的配置项,但是canal.instance.mysql.slaveId配置项需要每个实例唯一,并且不能和主库的serverId冲突,例如:

# 虚拟机中的配置
canal.instance.mysql.slaveId=654321 # 开发机中的配置
canal.instance.mysql.slaveId=654322

然后修改虚拟机/data/canal/conf/canal.properties配置,修改项主要包括:

Key Value
canal.zkServers 填写Zookeeper集群的host:port,这里填写192.168.56.200:2181
canal.serverMode kafka
canal.instance.global.spring.xml classpath:spring/default-instance.xml(一定要修改为此配置,基于Zookeeper的集群管理依赖于此配置)
canal.mq.servers 填写Kafka集群的host:port,这里填写192.168.56.200:9092

其他配置项可以按需修改。对于canal.propertiesCanal多个集群节点可以完全一致,写好一份然后拷贝使用即可。接着可以分别启动两个Canal服务,一般来说,先启动的节点会成为running节点:

  • 对于Linux系统,可以使用命令sh $CANAL_HOME/bin/startup.sh启动Canal
  • 对于Windows系统,直接挂起命令界面执行$CANAL_HOME/bin/startup.bat脚本即可。

Windows启动如果控制台报错ch.qos.logback.core.LogbackException: Unexpected filename extension of file...,其实是因为脚本中的logback配置文件路径占位符的变量没有预先设置值,见下图:

Linux下的启动日志(example.log):

Windows下的启动日志(canal.log):

测试Canal高可用集群

先启动虚拟机中的Canal服务,再启动本地开发机中的Canal服务:

可见当前的cluster列表中包含了两个host:port,而running节点中的信息只包含虚拟机的host:port,意味着当前运行节点时虚拟机中的Canal服务,本地开发机中的Canal服务作为备用节点。此时可以尝试在虚拟机中执行sh stop.sh关闭Canal服务:

可见cluster列表只剩下本地开发机中的Canal服务的host:port,而running节点中的信息也是指向此服务信息。至此成功验证了Canal主备模式的切换。此时可以再验证一下开发机中的example.log

说说Canal保存在Zookeeper中的数据节点

前文使用ZooInspector展示了Canal保存在Zookeeper中的节点信息,这里简单分析一下。节点树的结构如下:

节点路径 描述
/otter/canal 根目录
/otter/canal/cluster Canal集群节点信息
/otter/canal/destinations Canal所有Instance的信息

/otter/canal/cluster路径的展开如下:

# 其实就是挂载了所有集群节点的host:port信息
/otter/canal/cluster
- 192.168.56.1:11111
- 172.17.0.1:11111

/otter/canal/destinations路径会相对复杂,展开的信息如下:

/otter/canal/destinations
- Instance标识
- running 记录当前为此Instance提供服务状态为running的Canal节点 [EPHEMERAL类型]
- cluster 记录当前为此Instance提供服务的Canal集群节点列表
- Client序号标识
- running 客户端当前正在读取的running节点 [EPHEMERAL类型]
- cluster 记录当前读取此Instance的客户端节点列表
- cursor 记录客户端读取的position信息 # 例如
/otter/canal/destinations
- example
- running -> {"active":true,"address":"192.168.56.1:11111"}
- cluster
- 192.168.56.1:11111
- 172.17.0.1:11111
- 1001
- running
- cluster
- cursor

理解各个路径存放的信息,有利于在Canal集群出现故障的时候结合日志进行故障排查。

小结

Canal集群已经在生产跑了一段时间,大部分的问题和坑都已经遇到过,有些问题通过了屏蔽某些开关解决,一些遗留无法解决的问题也想办法通过预警手段人工介入处理。CanalHA其实是比较典型的主备模式,也就是同一个时刻,只有单个Canal服务对单个InstanceDestination)进行处理,想了下确实好像这样才能确保主备中继日志同步的基本有序,备用节点其实是完全划水不工作的(除了监听Zookeeper中的路径变更),一旦running节点出现故障或者宕机,备用节点就会提升为running节点,确保集群的可用性。

(本文完 c-3-d e-a-20200822)

Canalv1.1.4版本搭建HA集群的更多相关文章

  1. Hadoop集群搭建:用三台云服务器搭建HA集群(过程记录和分享)

    该文主要记录了自己用云服务器搭建集群的过程,也分享一些自己遇到的问题和解决方法.里面可能提及一些自己的理解,可能不够准确,希望大家能够指正我,谢谢. 1.什么是HA集群 HA :High Availa ...

  2. hadoop搭建HA集群之后不能自动切换namenode

    在搭好HA集群之后,想测试一下集群的高可用性,于是先把active的namenode给停掉: hadoop-daemon.sh stop namenode 或者直接kill掉该节点namenode的对 ...

  3. 基于Hadoop不同版本搭建hive集群(附配置文件)

    本教程采用了两种方案 一种是hive-1.21版本,hadoop版本为hadoop2.6.5 还有一种是主要讲基于hadoop3.x hive的搭建 先来第一种 一.本地方式(内嵌derby) 步骤 ...

  4. ZooKeeper学习之路 (九)利用ZooKeeper搭建Hadoop的HA集群

    Hadoop HA 原理概述 为什么会有 hadoop HA 机制呢? HA:High Available,高可用 在Hadoop 2.0之前,在HDFS 集群中NameNode 存在单点故障 (SP ...

  5. 二进制搭建Kubernetes集群(最新v1.16.0版本)

    目录 1.生产环境k8s平台架构 2.官方提供三种部署方式 3.服务器规划 4.系统初始化 5.Etcd集群部署 5.1.安装cfssl工具 5.2.生成etcd证书 5.2.1 创建用来生成 CA ...

  6. linux系统centOS7下搭建redis集群中ruby版本过低问题的解决方法

    问题描述: 在Centos7中,通过yum安装ruby的版本是2.0.0,但是如果有些应用需要高版本的ruby环境,比如2.2,2.3,2.4... 那就有点麻烦了,譬如:我准备使用redis官方给的 ...

  7. hadoop HA集群搭建步骤

      NameNode DataNode Zookeeper ZKFC JournalNode ResourceManager NodeManager node1 √   √ √   √   node2 ...

  8. 大数据-HBase HA集群搭建

    1.下载对应版本的Hbase,在我们搭建的集群环境中选用的是hbase-1.4.6 将下载完成的hbase压缩包放到对应的目录下,此处我们的目录为/opt/workspace/ 2.对已经有的压缩包进 ...

  9. hadoop namenode HA集群搭建

    hadoop集群搭建(namenode是单点的)  http://www.cnblogs.com/kisf/p/7456290.html HA集群需要zk, zk搭建:http://www.cnblo ...

随机推荐

  1. [COCOS2DX-LUA]0-006.cocos2dx中关于拖动屏幕物件,同时点击home键,返回后页面变黑的问题。

    基本信息介绍: 引擎框架: Quick-Cocos2dx-Community-3.6 测试机型: 魅族MX5 问题简介: 有拖动效果的物件,在拖动的工程中,手指不放,同时点击home键退到后台. 再返 ...

  2. Android 的OkHttp(发送网络请求)

    今天讲的是和HttpURLConnection差不多的OkHttp; 先把网站献上: 官网介绍okhttp的: https://square.github.io/okhttp/ 下载postman的: ...

  3. 还在纠结学什么编程语言吗?Python可能会“教”你做人

    这几年为什么Python在中国就火起来了? Python这个东西国,大概是从2017年末开始,突然就火了起来的.此前,对于Python,乃至编程,绝大多数程度上都是专业人士的话题,在普通大众层面上起不 ...

  4. mysql删除数据库提示mysql Error dropping database (can't rmdir './db'...

    1.执行ps aux | grep mysql,查看mysql的data目录,比如结果是--datadir=/var/lib/mysql. 2.进入data目录,删除以该数据库为名字的文件夹.cd / ...

  5. Github获8300星!用Python开发的一个命令行的网易云音乐

    最近在逛Github发现了一个非常有趣的库musicbox,是用纯Python打造的,收获了8300颗星.Python语言简单易学,好玩有趣,身边越来越多的小伙伴都开始学习Python.她的魅力非常大 ...

  6. Python爬虫开发:反爬虫措施以及爬虫编写注意事项

  7. Java不可不知的泛型使用

    前面的文章: 详解Java的对象创建 一文打尽Java继承的相关问题 一文打尽Java抽象类和接口的相关问题 本文介绍了Java的泛型的基本使用. 1. 为什么使用泛型 看下面一个例子: 为了说明问题 ...

  8. redis(二)redis的主从模式和集群模式

    redis(二)redis的主从模式和集群模式 主从模式 集群模式 主从模式 redis的主从模式,指的是针对多台redis实例时候,只存在一台主服务器master,提供读写的功能,同时存在依附在这台 ...

  9. C#-用Winform制作一个简单的密码管理工具

    为什么要做? 首先是为了练习一下c#. 想必大家都有过记不起某个平台的账号密码的经历,那种感受着实令人抓狂.那这么多账号密码根本记不住!我之前用python写过一个超级简单(连账号信息都写在代码里那种 ...

  10. C#图解教程(第四版)—02—类的基本概念

    类  是一种能 存储数据  并且  执行代码  的数据结构,他包含数据成员和函数成员 .成员可以是9种可能的成员类型的任意组合 字段 属性 方法 常量 构造函数 析构函数 运算符 索引器 事件 1 字 ...