Zookeeper实践与应用- Canal

基于MySql BinLog的增量订阅和消费组件:Canal

  • Cancal是阿里13年1月开源的一个基于MySql数据库Binlog实现的增量订阅和消费的组件。项目取名Canal取自管道的英文单词,流转的医生,是一个定位于基于MySql数据库Binlog增量日志来实现数据库镜像,试试备份和怎梁书记消费的通用组件。
  • 早期的数据库同步业务,大多使用MySql数据库的触发器机制(Trigger)来获取数据库的增量变更,之后逐步阐释基于数据库日志解析来获取数据,再次激起上实现数据同步,由此衍生出了数据库增量订阅和消费业务----Canal项目。

Canal核心思想

  • Canal工作原理比较简单,核心思想就是模拟MySql Slave的交互协议,将字节伪装称为一个MySql的Slave激起,不断向Master发送Dump请求。Master收到Dump后,开始推送对应Binary Log给这个Slave(其实是Canal)。Canal收到Binary log,解析出对应的Binary Log对象后就可以进行二次消费了,基本工作如下:
    在这里插入图片描述

Canal Server主备切换设计

  • 在Canal的设计中,基于对容灾的设计,会配置两个或者更多的Canal Server负责一个MySql数据库实例的数据增量复制,另外一个方面,为减少CanalServer的Dump请求对MySql Master带来的影响,要求不同Canal Server上的Instance在同一个时刻只能有一个处于Running状态,其他的instance都处于Standby状态,这就使得Canal必须具备主从切换能力,此部分功能利用Zookeeper来完成,如下图:
    在这里插入图片描述
  • 尝试启动: 每个Canal Server在启动某个Canal instance的时候,都会首先向Zookeeper进行一次阐释启动判断,都想Zookeeper创建同一个临时节点,那个Canal Server创建成功,就让哪一个启动。以“example”这个instance为例,都创建“/otter/canal/destinations/example/running”节点,Zookeeper保证只有一个成功
  • 启动instance: 假设最终IP:10.1.12.211的Canal Server成功创建,会将字节机器信息写入节点中,并同时启动instance,其他CanServer会将字节状态设置Standby同时对成功节点注册Watch监听,以监听节点变化情况。成功节点注册数据如下:
{"active":true,"address":"10.1.12.211:11111","cid":1}
  • 主备切换:CanalServer在运行过程中,发送异常,因为创建的是Zookeeper的临时节点,当Running状态的CanalServer挂点或者网络原因断开,那么“/otter/canal/destinations/example/running”节点就会在一段时间后消失。其他Standby状态的CanalServer已经添加过Watch,因此会接受到Zookeeper发来的通知,重复1 步骤以此实现主备切换

  • 特殊设计:Canal设计中,当有那种服务器网络闪断的假死清,导致Zookeeper任务其会话失效,此时其实CanalServer对应JVM并没有退出,状态正常,CanalServer做了一个策略:

    • 状态为Standby的CanalServer收到Running节点释放的通知后,会延迟一段时间抢占Running节点,而原来的Running状态的instance不需要等待直接获取Running节点。这样就尽可能保证瞬时假死情况下不需要切换避免了五位的资源释放和重新分配,目前延迟时间是5秒,即Running节点针对假死状态的保护器为5秒

Canal Server的HA设计

  • Canal Servers进行数据消费钱,需要找到Master的CanalServer节点,在上文中已经讲了,针对每一个数据复制实例,例如example,都会在“/otter/canal/destinations/example/running” 节点记录正在运行的CanalServer,所有CanalServer链接Zookeeper后读取这个节点信息即可
  1. 从Zookeeper中读取当前处于Running状态的server:CanalClient启动会首先从“/otter/canal/destinations/example/running” 节点读取当前Running状态的Server,同时客户端也会将字节的信息注册到Zookeeper的“/otter/canal/destinations/example/1001/running” 下面,其中1001目录层级是代表客户端唯一标识节点内容如下:
{"active":true,"address":"10.1.12.211:50544","clientId":1001}
  1. 注册Running节点数据变化的监听: 由于CanalServer有挂掉的风险,CanalClient还会对“/otter/canal/destinations/example/running”节点注册一个监听,一旦server主备切换,Client随时能感知到。
  2. 链接对应RunningServer进行数据消费。

数据消费点位记录

  • 由于存在CanalClient重启或者其他变化,为避免数据消费顺序错乱,Canal必须对数据消费点位进行实时的记录,也就是记录下本次读取到的Binlog日志到第几行了,数据消费后,CanalServer会在Zookeeper上记录当前最后一次消费成功的Binarylog点位,一旦发生Client重启,只需从这个点位后一个点位开始消费,具体做法如下:
  • 在Zookeeper的“/otter/canal/destinations/example/1001/cursor”节点中记录下客户端消费的详细点位信息:
    在这里插入图片描述
  • 具体内容如下:
{"@type":"com.alibaba.otter.canal.protocol.position.LogPosition","identity":{"slaveId":-1,"sourceAddress":{"address":"10.21.16.8","port":3306}},"postion":{"gtid":"","included":false,"journalName":"mysql-bin.004073","position":82751773,"serverId":109065,"timestamp":1589508966000}}

上一篇Zookeeper–Watcher机制源码剖析二
下一篇Zookeeper实践与应用-- Nginx负载均衡差异

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/310612.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

你遇到的面试官是「伯乐」吗?

之前写了一篇应应聘者视角的「面试中要注意的点」,《聊聊面试的事(应聘方)》。这次再来一篇面试官视角的。如果你不是面试官,也没关系。所谓“知己知彼,方能百战百胜”,了解一下面试官在面试时的侧重点&…

记录一次线上超时异常查询

线上事故复盘 前言 前一次上线,当时正常,第二天发现有部分超时报警,最终发现应为Dubbo接口一次传输数据量太大导致线程虚拟内存占用 线上问题排查过程 报警邮件中查询到有一部分接口超时量激增,查询定位到某个Dubbo接口&#x…

没用过.gitignore还敢自称高级开发?

Git是跟踪项目中所有文件的好工具, 但是,您会希望在项目的整个生命周期中不要跟踪某些文件及其变更。系统文件(i.e. Mac系统的.Ds_Store)应用程序配置文件(i.e. app.config, .env)构建组件(i.e.…

支付价格计算中精度问题之double,float

前言 前段时间开发新的微信小程序,借此机会将老掉牙的支付模块重构,并且支持现金支付(之前都是虚拟币支付),在重构期间遇到计算上的一些精度问题,虽然数额影响非常小但是影响比较大,我觉得有必…

.net core 集成 sentry 进行异常报警

.net core 集成 sentry 进行异常报警IntroSentry 是一个实时事件日志记录和汇集的平台。其专注于错误监控以及提取一切事后处理所需信息而不依赖于麻烦的用户反馈。它分为客户端和服务端,客户端(目前客户端有 C#, Python, PHP, JavaScript, Ruby等多种语言)就嵌入在…

[Qt入门]QTableWidget控件创建

#include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent) :QWidget(parent),ui(new Ui::Widget) {ui->setupUi(this);//TableWidget控件//设置列数ui->tableWidget->setColumnCount(3);//设置水平表头ui->tableWidget->…

Zookeeper--Watcher机制源码剖析一

Watcher-- 数据变更通知 我们知道Zookeeper提供来分布式数据的订阅/发布功能,一个典型的发布/订阅模型系统定义了一种一对多的订阅关系,能让多个订阅者同时监听某个主题对象,当这个被监听对象自身状态发生变化时候,会通知所有订阅…

.NET Core 3.1 的REST 和gRPC 性能测试

看到越南小哥 的github 上的Evaluating Performance of REST vs. gRPC , 使用的是.NET Core 3.0 , 今天我把它升级到.NET Core 3.1 同样做了一个测试,文章的结果和他的博客文章是一样的:https://dev.to/thangchung/performance-benchmark-grp…

Zookeeper--Watcher机制源码剖析二

Watcher触发 我们从实际操作时候的表现来看Watcher的触发,比如Zookeeper中NodeDataChanged时间的触发是“Watcher监听的对应数据节点的数据内容发生变更”,需要修改节点数据那么必然和数据节点存储的位置DataTree有关系,我们从这里去寻找修改…

吴军《硅谷来信》工作篇学习总结

【学习总结】| 作者 / Edison Zhou这是恰童鞋骚年的第215篇原创文章2018年在得到App上订阅了吴军老师的《硅谷来信》,从此每天的碎片时间就开始听吴军老师在大洋彼岸寄来的信件了。整个来信涵盖了职业发展、工作效率、业余生活等多个主题,从吴军老师的视…

Zookeeper实践与应用-- Nginx负载均衡差异

Nginx/ZooKeeper 负载均衡的差异 Nginx 是我们常见的反向代理服务器,也被广泛的用作负载均衡服务器ZooKeeper是分布式协调服务框架,有时也被用来做负载均衡 Nginx Nginx负载均衡配置非常简单,吧多个Web Server配置到nginx中,用…

从对我的质疑说起,谈谈Linux下的文件删除

特特本来就是个刚毕业的小菜,很多知识都是靠着大家的指点才慢慢学会的。之前在一篇"纯属虚构"的文章 (鹅厂后台开发工程师的工作日常) 提到使用 rm 命令删除一个近 100 G 的 log 文件。很荣幸,这篇文章被一个大号转载了,获得了很不…

Zookeeper实践与应用--分布式锁实现

分布式锁 分布式锁是控制分布式系统之间同步访问资源的一种方式,如果不同系统是同一个系统的不同主机之间共享一个或一组资源,那么访问这些资源的时候,往往需要通过一些呼哧手段来防止彼此之间的干扰保证统一性,因此需要分布式锁…

关于 Blazor Server Side 的一些杂项, 感想

在2016年, 本人就开始了一个内部项目, 其特点就是用C#构建DOM树, 然后把DOM同步到浏览器中显示. 并且在一些小工程中使用.3年下来, 效果很不错, 但因为是使用C#来构建控件树, 在没有特定语法的情况下, 代码风格不是那么好.典型的风格大概是这样的:这个模式挺好的, 有点嫌弃C#代…

重现江湖!大数据高并发——架构师秘籍

大数据高并发的话题屡见不鲜,各种应对的方式方法也四处可见。然而笔试面试中一问就懵,简直是高薪拦路虎。为什么呢?究其原因,还是思路不清晰,缺乏实操,所以一问就倒。作为专注.Net领域十几年的老司机&#…

[剑指offer]面试题4:替换空格

面试题4:替换空格 题目:请实现一个函数,把字符串中的每个空格替换成"%20"。例如输入“We are happy.”,则输出“We%20are%20happy.”。 ❖ 时间复杂度为O(n2)的解法,不足以拿到Offer…

Zookeepe实践与应用--分布队列

分布式队列 接触到不少分布式队列的产品,比如,ActiveMq,RocketMQ,kafka等消息中间价,现在我们看看Zookeeper实现的分布式队列。分布式队列简单讲就可以分两个部分,一种是先进先出,另外一种是等…

ASP.NET Core+Quartz.Net实现web定时任务

点击蓝色“Dotnet Plus”关注我哟加个“星标”,每天清晨 07:25,干货推送!作为一枚后端程序狗,项目实践常遇到定时任务的工作,最容易想到的的思路就是利用Windows计划任务/wndows service程序/Crontab程序等主机方法在主…

Redis基础数据结构内部实现简单介绍

5种基础数据结构 Redis有5种基础数据结构,分别是:String(字符串),list(列表),hash(字典),set(集合),zset&…

[剑指offer]面试题7:用两个栈实现队列

面试题7:用两个栈实现队列 题目:用两个栈实现一个队列。队列的声明如下,请实现它的两个函数appendTail和deleteHead,分别完成在队列尾部插入结点和在队列头部删除结点的功能。 用两个栈模拟一个队列的操作: 代码如下: #include …