来自:https://blog.csdn.net/u012985132/article/details/74964366/

关系型数据库和Hadoop生态的沟通越来越密集,时效要求也越来越高。本篇就来调研下实时抓取MySQL更新数据到HDFS。

本篇仅作为调研报告。

初步调研了canal(Ali)+kafka connect+kafka、maxwell(Zendesk)+kafka和mysql_streamer(Yelp)+kafka。这几个工具抓取MySQL的方式都是通过扫描binlog,模拟MySQL master和slave(Mysql Replication架构–解决了:数据多点备份,提高数据可用性;读写分流,提高集群的并发能力。(并非是负载均衡);让一些非实时的数据操作,转移到slaves上进行。)之间的协议来实现实时更新的

先科普下Canal

Canal简介

原理

Canal原理图

原理相对比较简单:

  1. canal模拟mysql slave的交互协议,伪装自己为mysql slave,向mysql master发送dump协议
  2. mysql master收到dump请求,开始推送(slave拉取,不是master主动push给slaves)binary log给slave(也就是canal)
  3. canal解析binary log对象(原始为byte流)

架构

Canal架构图

组件说明:

  1. server代表一个canal运行实例,对应于一个jvm
  2. instance对应于一个数据队列(1个server对应1..n个instance)

而instance模块又由eventParser(数据源接入,模拟slave协议和master进行交互,协议解析)、eventSink(Parser和Store连接器,进行数据过滤,加工,分发的工作)、eventStore(数据存储)和metaManager(增量订阅&消费信息管理器)组成。

  • EventParser在向mysql发送dump命令之前会先从Log Position中获取上次解析成功的位置(如果是第一次启动,则获取初始指定位置或者当前数据段binlog位点)。mysql接受到dump命令后,由EventParser从mysql上pull binlog数据进行解析并传递给EventSink(传递给EventSink模块进行数据存储,是一个阻塞操作,直到存储成功),传送成功之后更新Log Position。流程图如下:

    EventParser流程图

  • EventSink起到一个类似channel的功能,可以对数据进行过滤、分发/路由(1:n)、归并(n:1)和加工。EventSink是连接EventParser和EventStore的桥梁。

  • EventStore实现模式是内存模式,内存结构为环形队列,由三个指针(Put、Get和Ack)标识数据存储和读取的位置。

  • MetaManager是增量订阅&消费信息管理器,增量订阅和消费之间的协议包括get/ack/rollback,分别为:

Message getWithoutAck(int batchSize),允许指定batchSize,一次可以获取多条,每次返回的对象为Message,包含的内容为:batch id[唯一标识]和entries[具体的数据对象]
void rollback(long batchId),顾命思议,回滚上次的get请求,重新获取数据。基于get获取的batchId进行提交,避免误操作
void ack(long batchId),顾命思议,确认已经消费成功,通知server删除数据。基于get获取的batchId进行提交,避免误操作

增量订阅和消费之间的协议交互如下:

增量订阅和消费协议

canal的get/ack/rollback协议和常规的jms协议有所不同,允许get/ack异步处理,比如可以连续调用get多次,后续异步按顺序提交ack/rollback,项目中称之为流式api.

流式api设计的好处:

  • get/ack异步化,减少因ack带来的网络延迟和操作成本 (99%的状态都是处于正常状态,异常的rollback属于个别情况,没必要为个别的case牺牲整个性能)
  • get获取数据后,业务消费存在瓶颈或者需要多进程/多线程消费时,可以不停的轮询get数据,不停的往后发送任务,提高并行化. (在实际业务中的一个case:业务数据消费需要跨中美网络,所以一次操作基本在200ms以上,为了减少延迟,所以需要实施并行化)

流式api设计示意图如下:

流式api

  • 每次get操作都会在meta中产生一个mark,mark标记会递增,保证运行过程中mark的唯一性
  • 每次的get操作,都会在上一次的mark操作记录的cursor继续往后取,如果mark不存在,则在last ack cursor继续往后取
  • 进行ack时,需要按照mark的顺序进行数序ack,不能跳跃ack. ack会删除当前的mark标记,并将对应的mark位置更新为last ack cusor
  • 一旦出现异常情况,客户端可发起rollback情况,重新置位:删除所有的mark, 清理get请求位置,下次请求会从last ack cursor继续往后取

这个流式api是不是类似hdfs write在pipeline中传输packet的形式,先将packet放入dataQueue,然后向下游传输,此时将packet放入ackQueue等到下游返回的ack,这也是异步的。

HA机制

canal是支持HA的,其实现机制也是依赖zookeeper来实现的,用到的特性有watcher和EPHEMERAL节点(和session生命周期绑定),与HDFS的HA类似。

canal的ha分为两部分,canal server和canal client分别有对应的ha实现

  • canal server: 为了减少对mysql dump的请求,不同server上的instance(不同server上的相同instance)要求同一时间只能有一个处于running,其他的处于standby状态(standby是instance的状态)。
  • canal client: 为了保证有序性,一份instance同一时间只能由一个canal client进行get/ack/rollback操作,否则客户端接收无法保证有序。

server ha的架构图如下:

ha

大致步骤:

  1. canal server要启动某个canal instance时都先向zookeeper进行一次尝试启动判断(实现:创建EPHEMERAL节点,谁创建成功就允许谁启动)
  2. 创建zookeeper节点成功后,对应的canal server就启动对应的canal instance,没有创建成功的canal instance就会处于standby状态
  3. 一旦zookeeper发现canal server A创建的instance节点消失后,立即通知其他的canal server再次进行步骤1的操作,重新选出一个canal server启动instance。
  4. canal client每次进行connect时,会首先向zookeeper询问当前是谁启动了canal instance,然后和其建立链接,一旦链接不可用,会重新尝试connect。

Canal Client的方式和canal server方式类似,也是利用zookeeper的抢占EPHEMERAL节点的方式进行控制.

Canal部署及使用

MySQL配置

canal同步数据需要扫描MySQL的binlog日志,而binlog默认是关闭的,需要开启,并且为了保证同步数据的一致性,使用的日志格式为row-based replication(RBR),在my.conf中开启binlog,


1
2
3
4

[mysqld]
log-bin=mysql-bin #添加这一行就ok
binlog-format=ROW #选择row模式
server_id=1 #配置mysql replaction需要定义,不能和canal的slaveId重复

更改my.conf之后,需要重启MySQL,重启的方式有很多找到合适自己的就行。

Canal配置

由上面的介绍得知Canal由ServerInstance组成,而Server中又可以包含很多个Instance,一个Instance对应一个数据库实例,则Canal将配置分为两类,一类是server的配置,名字为canal.properties,另一类是instance的配置,名字为instance.properties,一般会在conf目录下新建一个instance同名的目录,将其放入此目录中。

先介绍canal.properties中的几个关键属性

参数名字 参数说明 默认值
canal.destinations 当前server上部署的instance列表
canal.conf.dir conf/目录所在的路径 ../conf
canal.instance.global.spring.xml 全局的spring配置方式的组件文件 classpath:spring/file-instance.xml 
(spring目录相对于canal.conf.dir)
canal.zkServers canal server链接zookeeper集群的链接信息
canal.zookeeper.flush.period canal持久化数据到zookeeper上的更新频率,单位毫秒 1000
canal.file.data.dir canal持久化数据到file上的目录 ../conf (默认和instance.properties为同一目录,方便运维和备份)
canal.file.flush.period canal持久化数据到file上的更新频率,单位毫秒 1000
canal.instance.memory.batch.mode canal内存store中数据缓存模式 
1. ITEMSIZE : 根据buffer.size进行限制,只限制记录的数量 
2. MEMSIZE : 根据buffer.size * buffer.memunit的大小,限制缓存记录的大小
MEMSIZE
canal.instance.memory.buffer.size canal内存store中可缓存buffer记录数,需要为2的指数 16384
canal.instance.memory.buffer.memunit 内存记录的单位大小,默认1KB,和buffer.size组合决定最终的内存使用大小 1024

下面看下instance.properties,这里的属性较少:

参数名字 参数说明 默认值
canal.instance.mysql.slaveId mysql集群配置中的serverId概念,需要保证和当前mysql集群中id唯一 1234
canal.instance.master.address mysql主库链接地址 127.0.0.1:3306
canal.instance.master.journal.name mysql主库链接时起始的binlog文件
canal.instance.master.position mysql主库链接时起始的binlog偏移量
canal.instance.master.timestamp mysql主库链接时起始的binlog的时间戳
canal.instance.dbUsername mysql数据库帐号 canal
canal.instance.dbPassword mysql数据库密码 canal
canal.instance.defaultDatabaseName mysql链接时默认schema
canal.instance.connectionCharset mysql 数据解析编码 UTF-8
canal.instance.filter.regex mysql 数据解析关注的表,Perl正则表达式. 
多个正则之间以逗号(,)分隔,转义符需要双斜杠
.*\\..*

除了上面两个配置文件,conf目录下还有一个目录需要强调下,那就是spring目录,里面存放的是instance.xml配置文件,目前默认支持的instance.xml有memory-instance.xml、file-instance.xml、default-instance.xml和group-instance.xml。这里主要维护的增量订阅和消费的关系信息(解析位点和消费位点)。

对应的两个位点组件,目前都有几种实现:

  • memory (memory-instance.xml中使用)
  • zookeeper
  • mixed
  • file (file-instance.xml中使用,集合了file+memory模式,先写内存,定时刷新数据到本地file上)
  • period (default-instance.xml中使用,集合了zookeeper+memory模式,先写内存,定时刷新数据到zookeeper上)

分别介绍下这几种配置的功能

  • memory-instance.xml:

所有的组件(parser , sink , store)都选择了内存版模式,记录位点的都选择了memory模式,重启后又会回到初始位点进行解析

特点:速度最快,依赖最少(不需要zookeeper)

场景:一般应用在quickstart,或者是出现问题后,进行数据分析的场景,不应该将其应用于生产环境

  • file-instance.xml:

所有的组件(parser , sink , store)都选择了基于file持久化模式(组件内容持久化的file存在哪里???),注意,不支持HA机制.

特点:支持单机持久化

场景:生产环境,无HA需求,简单可用.

  • default-instance.xml:

所有的组件(parser , sink , store)都选择了持久化模式,目前持久化的方式主要是写入zookeeper,保证数据集群共享.(所有组件持久化的内容只有位置信息吧???)

特点:支持HA

场景:生产环境,集群化部署.

  • group-instance.xml:

主要针对需要进行多库合并时,可以将多个物理instance合并为一个逻辑instance,提供客户端访问。

场景:分库业务。 比如产品数据拆分了4个库,每个库会有一个instance,如果不用group,业务上要消费数据时,需要启动4个客户端,分别链接4个instance实例。使用group后,可以在canal server上合并为一个逻辑instance,只需要启动1个客户端,链接这个逻辑instance即可.

canal example 部署

  • 在需要同步的MySQL数据库中创建一个用户,用来replica数据,这里新建的用户名和密码都为canal,命令如下:

1
2
3
4

CREATE USER canal IDENTIFIED BY 'canal';
GRANT SELECT, REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'canal'@'%';
-- GRANT ALL PRIVILEGES ON *.* TO 'canal'@'%' ;
FLUSH PRIVILEGES;
  • Mysql创建canal用户并为其赋所需权限之后,需要对Canal的配置文件(canal.properties和instance.properties)进行设置。

canal.properties和instance.properties里采用默认配置即可(这里只是运行个样例,生产中可以参考具体的参数属性进行设置),

  • Canal配置好之后,启动Canal client(client的作用是将Canal里的解析的binlog日志固化到存储介质中)。

client组件Canal本身是不提供的,需要根据api进行开发,这里将官方提供的client代码打包成jar进行消费Canal信息。

canal HA配置

canal的HA机制是依赖zk来实现的,需要更改canal.properties文件,修改内容如下:


1
2
3
4

# zk集群地址
canal.zkServers=10.20.144.51:2181
# 选择记录方式
canal.instance.global.spring.xml = classpath:spring/default-instance.xml

更改两台canal机器上instance实例的配置instance.properties,修改内容如下:


1
2

canal.instance.mysql.slaveId = 1234 ##另外一台机器改成1235,保证slaveId不重复即可
canal.instance.master.address = 10.20.144.15:3306

配置好之后启动canal进程,在两台服务器上执行sh bin/startup.sh

client进行消费时,可以直接指定zookeeper地址和instance name,也可以让canal client会自动从zookeeper中的running节点,获取当前服务的工作节点,然后与其建立链接。

maxwell简介

maxwell实时抓取mysql数据的原理也是基于binlog,和canal相比,maxwell更像是canal server + 实时client。(数据抽取 + 数据转换)

maxwell集成了kafka producer,直接从binlog获取数据更新并写入kafka,而canal则需要自己开发实时client将canal读取的binlog内容写入kafka中。

maxwell特色:

  • 支持bootstrap启动,同步历史数据
  • 集成kafka,直接将数据落地到kafka
  • 已将binlog中的DML和DDL进行了模式匹配,将其解码为有schema的json(有利于后期将其重组为nosql支持的语言)
    {“database”:”test”,”table”:”e”,”type”:”update”,”ts”:1488857869,”xid”:8924,”commit”:true,”data”:{“id”:1,”m”:5.556666,”torvalds”:null},”old”:{“m”:5.55}}

缺点:

  • 一个MySQL实例需要对应一个maxwell进程
  • bootstrap的方案使用的是select *

maxwell的配置文件只有一个config.properties,在home目录。其中除了需要配置mysql master的地址、kafka地址还需要配置一个用于存放maxwell相关信息的mysql地址,maxwell会把读取binlog关系的信息,如binlog name、position。

工具对比

以上是Canal的原理及部署,其余类似maxwell和mysql_streamer对mysql进行实时数据抓取的原理一样就不再进行一一介绍,这里只对他们进行下对比:

特色 Canal Maxwell mysql_streamer
语言 Java Java Python
活跃度 活跃 活跃 不活跃
HA 支持 定制 支持
数据落地 定制 落地到kafka 落地到kafka
分区 支持 不支持 不支持
bootstrap 不支持 支持 支持
数据格式 格式自由 json(格式固定) json(格式固定)
文档 较详细 较详细 略粗
随机读 支持 支持 支持

以上只是将mysql里的实时变化数据的binlog以同种形式同步到kafka,但要实时更新到hadoop还需要使用一个实时数据库来存储数据,并自定制开发将kafka中数据解析为nosql数据库可以识别的DML进行实时更新Nosql数据库,使其与MySQL里的数据实时同步。

基础架构

架构图如下:

基础架构图

虚线框是可选的方案

方案对比

  1. 方案1使用阿里开源的Canal进行Mysql binlog数据的抽取,另需开发一个数据转换工具将从binlog中解析出的数据转换成自带schema的json数据并写入kafka中。而方案2使用maxwell可直接完成对mysql binlog数据的抽取和转换成自带schema的json数据写入到kafka中。
  2. 方案1中不支持表中已存在的历史数据进行同步,此功能需要开发(如果使用sqoop进行历史数据同步,不够灵活,会使结果表与原始表结构相同,有区别于数据交换平台所需的schema)。方案2提供同步历史数据的解决方案。
  3. 方案1支持HA部署,而方案2不支持HA

方案1和方案2的区别只在于kafka之前,当数据缓存到kafka之后,需要一个定制的数据路由组件来将自带schema的数据解析到目标存储中。
数据路由组件主要负责将kafka中的数据实时读出,写入到目标存储中。(如将所有日志数据保存到HDFS中,也可以将数据落地到所有支持jdbc的数据库,落地到HBase,Elasticsearch等。)

综上,
方案1需要开发的功能有:

  • bootstrap功能
  • 实时数据转换工具
  • 数据路由工具

方案2需要开发的功能有:

  • 数据路由工具
  • HA模块(初期可暂不支持HA,所以开发紧急度不高)

数据路由工具是两个方案都需要开发的,则我比较偏向于第二种方案,因为在初期试水阶段可以短期出成果,可以较快的验证想法,并在尝试中能够较快的发现问题,好及时的调整方案。即使方案2中maxwell最终不能满足需求,而使用canal的话,我们也可能将实时数据转换工具的数据输出模式与maxwell一致,这样初始投入人力开发的数据路由工具依然可以继续使用,而不需要重新开发。

把增量的Log作为一切系统的基础。后续的数据使用方,通过订阅kafka来消费log。

比如:
大数据的使用方可以将数据保存到Hive表或者Parquet文件给Hive或Spark查询;
提供搜索服务的使用方可以保存到Elasticsearch或HBase 中;
提供缓存服务的使用方可以将日志缓存到Redis或alluxio中;
数据同步的使用方可以将数据保存到自己的数据库中;
由于kafka的日志是可以重复消费的,并且缓存一段时间,各个使用方可以通过消费kafka的日志来达到既能保持与数据库的一致性,也能保证实时性;

{“database”:”test”,”table”:”e”,”type”:”update”,”ts”:1488857869,”xid”:8924,”commit”:true,”data”:{“id”:1,”m”:5.556666,”torvalds”:null},”old”:{“m”:5.55}}

{“database”:”test”,”table”:”e”,”type”:”insert”,”ts”:1488857922,”xid”:8932,”commit”:true,”data”:{“id”:2,”m”:4.2,”torvalds”:null}}

20180705关于mysql binlog的解析方式的更多相关文章

  1. MySQL binlog格式解析

    MySQL binlog格式解析   binlog想必大家都不陌生,在主从复制或者某些情况下的数据恢复会用到.由于binlog是二进制数据,要查看一般都借助mysqlbinlog工具.这篇笔记分析了b ...

  2. Mysql binlog日志解析

    1. 摘要: Mysql日志抽取与解析正如名字所将的那样,分抽取和解析两个部分.这里Mysql日志主要是指binlog日志.二进制日志由配置文件的log-bin选项负责启用,Mysql服务器将在数据根 ...

  3. MySQL bin-log 日志清理方式

    MySQL bin-log 作用   1.数据恢复:如果你的数据库出问题了,而你之前有过备份,那么可以看日志文件,找出是哪个命令导致你的数据库出问题了,想办法挽回损失. 2.主从服务器之间同步数据:主 ...

  4. 转载:阿里canal实现mysql binlog日志解析同步redis

    from: http://www.cnblogs.com/duanxz/p/5062833.html 背景 早期,阿里巴巴B2B公司因为存在杭州和美国双机房部署,存在跨机房同步的业务需求.不过早期的数 ...

  5. 阿里云mysql数据库恢复总结,mysql binlog日志解析

    由于意外..阿里云mysql中有一张表被全部删除了,深吸三口气候,开始解决. 首先用凌晨的自动备份的,进行全量恢复,然后找binlog日志(见下文),查找从全量备份到数据删除之间的记录 这导致了一个问 ...

  6. MySQL binlog反解析

    反解析delete语句 背景:delete table忘了加条件导致整张表被删除 恢复方式:直接从binlog里反解析delete语句为insert进行恢复 导出删指定表的DELETE语句: # my ...

  7. 对MySQL binlog日志解析,统计每张表的DML次数

    想要获取每天数据库每张表的DML的次数,统计热度表,可以使用该脚本 # coding:utf-8 # 解析binlog,统计热度表,表的DML个数 import sys import os # mys ...

  8. MySQL Binlog 介绍

    Binlog 简介 MySQL中一般有以下几种日志: 日志类型 写入日志的信息 错误日志 记录在启动,运行或停止mysqld时遇到的问题 通用查询日志 记录建立的客户端连接和执行的语句 二进制日志 记 ...

  9. mysql binlog解析概要

    1,dump协议: 根据数据库的ip+port创建socket,如果创建成功,说明链接建立成功,接下来是使用dump协议订阅binlog 链接建立成功之后,服务端会主动向客户端发送如下问候信息gree ...

随机推荐

  1. 对象的属性类型 和 VUE的数据双向绑定原理

    如[[Configurable]] 被两对儿中括号 括起来的表示 不可直接访问他们 修改属性类型:使用Object.defineProperty()  //IE9+  和标准浏览器  支持 查看属性的 ...

  2. $CF19A\ World\ Football\ Cup$

    炒鸡\(6\)批的模拟题. 注意的是输入 把握好空格 大小写. 根据题目的这句话来排序 积分榜是按照以下原则制作的:胜利一个队得3分,平分1分,失败0分. 首先,球队按积分顺序排在积分榜上,分数相等比 ...

  3. Ray Wenderlich 的 Objective-C编码规范

    由于我正在准备模仿饿了么这个app,到时可能有些iOS开发者参与进来.这时如果每个人的Objective-C编码风格都不一样,这样不易于保持代码一致性和难以Code Review.所以我在网上搜索到  ...

  4. httponlycookie

    cookie cookie是目前标识用户身份一项非常流行的技术:设置httponly的cookie客户端是不能通过js来修改的:你以为这样就万事大吉,没有办法伪造了吗? 背景介绍 假设网站A通过设置h ...

  5. iOS布局分类

    1.线性布局: 2.集合布局: 3.单元布局: 需要考虑因素: 空间充足.空间不足时内容.尺寸的取舍.

  6. Clistctrl使用

    CListCtrl控件使用方法总结 今天第一次用CListCtrl控件,遇到不少问题,查了许多资料,现将用到的一些东西总结如下: 以下未经说明,listctrl默认view 风格为report 相关类 ...

  7. CAD在网页中如何实现嵌套打印?

    当用户需要打印两个控件的图纸时,可以采用嵌套打印实现.点击此处在线演示. 实现嵌套打印功能,首先将两个控件放入网页中,js代码如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ...

  8. MySql-了解存储引擎

    怎么应对不同版本 在不同的 mysql 版本中,很多特性和语法有可能是不一样的,我们怎么样才能知道当前版本的语法是什么样呢?最好的办法是学会使用 mysql 的帮助. A.按照层次看帮助 例如:mys ...

  9. vcenter6.5安装问题

    vcenter6.5 有2个安装包1个vim (windows系统)   1个vcsa(linux) 安装vcsa遇到如下问题: 1.版本bug 网上一般找到的镜像是VMware-VCSA-all-6 ...

  10. sql学习笔记:表的运算

    在MICK的<SQL基础教程>里读到的一章,写的很好,之前很乱的思路变清晰了很多.简单来说,表的运算主要是两种:列的运算和行的运算. 表的加减法 这里是对表的列操作(向下扩展).因此,按照 ...