互联网应用随着业务的发展,部分单表数据体量愈来愈大,应对服务性能与稳定的考虑,有作分库分表、数据迁移的须要,本文介绍了vivo账号应对以上需求的实践。java
Canal 是阿里巴巴开源项目,关于什么是 Canal?又能作什么?我会在后文为你们一一介绍。
在本文您将能够了解到vivo账号使用 Canal 解决了什么样的业务痛点,基于此但愿对您所在业务能有一些启示。mysql
Canal [kə'næl],译意为水道/管道/沟渠,主要用途是基于 MySQL 数据库增量日志解析,提供增量数据订阅和消费。git
早期阿里巴巴由于杭州和美国双机房部署,存在跨机房同步的业务需求,实现方式主要是基于业务 trigger 获取增量变动。从 2010 年开始,业务逐步尝试数据库日志解析获取增量变动进行同步,由此衍生出了大量的数据库增量订阅和消费业务。github
Canal最核心的运行机制就是依赖于MySQL的主备复制,咱们优先简要说明下MySQL主备复制原理。sql
MySQL master 将数据变动写入二进制日志( binary log, 其中记录叫作二进制日志事件binary log events,能够经过 show binlog events 进行查看)。数据库
MySQL slave 将 master 的 binary log events 拷贝到它的中继日志(relay log)。api
MySQL slave 重放 relay log 中事件,将数据变动反映它本身的数据。数组
MySQL-Binlog是 MySQL 数据库的二进制日志,用于记录用户对数据库操做的SQL语句(除了数据查询语句)信息。缓存
若是后续咱们须要配置主从数据库,若是咱们须要从数据库同步主数据库的内容,咱们就能够经过 Binlog来进行同步。网络
Canal 模拟MySQL slave的交互协议,假装本身为MySQL slave,向MySQL master发送dump协议。
MySQL master收到dump请求,开始推送binary log给slave(也就是Canal)。
Canal 解析 binary log 对象(原始为byte流)。
Canal 把解析后的 binary log 以特定格式的进行推送,供下游消费。
说明:
instance模块:
负责binlog对象总体的发布订阅管理器,相似于MQ。
下面咱们来一块儿看下Canal内部封装的 Binlog对象格式,更好的理解 Canal。
Canal可以同步 DCL、 DML、 DDL。
业务一般关心 INSERT、 UPDATE、 DELETE引发的数据变动。
EntryProtocol.proto
Entry Header logfileName [binlog文件名] logfileOffset [binlog position] executeTime [binlog里记录变动发生的时间戳] schemaName [数据库实例] tableName [表名] eventType [insert/update/delete类型] entryType [事务头BEGIN/事务尾END/数据ROWDATA] storeValue [byte数据,可展开,对应的类型为RowChange] RowChange isDdl [是不是ddl变动操做,好比create table/drop table] sql [具体的ddl sql] rowDatas [具体insert/update/delete的变动数据,可为多条,1个binlog event事件可对应多条变动,好比批处理] beforeColumns [Column类型的数组] afterColumns [Column类型的数组] Column index [column序号] sqlType [jdbc type] name [column name] isKey [是否为主键] updated [是否发生过变动] isNull [值是否为null] value [具体的内容,注意为文本]
下面咱们经过实际代码逻辑的判断,查看 Binlog解析成Canal 对象的数据模型,加深理解
线上服务的稳定性极为重要,Canal是支持HA的,其实现机制也是依赖Zookeeper来实现的,与HDFS的HA相似。
Canal的HA分为两部分,Canal server和Canal client分别有对应的HA实现。
依赖Zookeeper的特性(本文不着重讲解zookeeper特性,请在网络上查找对应资料):
大体步骤:
Canal server要启动某个canal instance时都先向zookeeper进行一次尝试启动判断 (实现:建立EPHEMERAL节点,谁建立成功就容许谁启动)。
建立 ZooKeeper节点成功后,对应的Canal server就启动对应的Canal instance,没有建立成功的Canal instance就会处于standby状态。
一旦ZooKeeper发现Canal server A建立的节点消失后,当即通知其余的Canal server再次进行步骤1的操做,从新选出一个Canal server启动instance。
Canal client每次进行connect时,会首先向ZooKeeper询问当前是谁启动了Canal instance,而后和其创建连接,一旦连接不可用,会从新尝试connect。
上面介绍了Canal 的原理与运行机制,下面咱们从实际场景来看,Canal 可以为咱们业务场景解决什么样的问题。
业务在发展初期,为了快速支撑业务发展,不少数据存储设计较为粗放,好比用户表、订单表可能都会设计为单表,此时常规手段会采用分库分表来解决容量和性能问题。
但数据迁移会面临最大的问题:线上业务须要正常运行,若是数据在迁移过程当中有变动,如何保证数据一致性是最大的挑战。
基于Canal,经过订阅数据库的 Binlog,能够很好地解决这一问题。
可详见下方vivo账号的不停机迁移实践。
互联网业务数据源不只仅为数据库,好比 Redis 在互联网业务较为经常使用,在数据变动时须要刷新缓存,常规手段是在业务逻辑代码中手动刷新。
基于Canal,经过订阅指定表数据的Binlog,能够异步解耦刷新缓存。
另外一种常见应用场景是“下发任务”,当数据变动时须要通知其余依赖系统。
其原理是任务系统监听数据库变动,而后将变动的数据写入MQ/Kafka进行任务下发。
好比账号注销时下游业务方须要订单此通知,为用户删除业务数据,或者作数据归档等。
基于Canal能够保证数据下发的精确性,同时业务系统中不会散落着各类下发MQ的代码,从而实现了下发归集,以下图所示:
在大型网站架构中,数据库都会采用分库分表来解决容量和性能问题,但分库分表以后带来的新问题。
好比不一样维度的查询或者聚合查询,此时就会很是棘手。通常咱们会经过数据异构机制来解决此问题。
所谓的数据异构,那就是将须要join查询的多表按照某一个维度又聚合在一个DB中。
基于Canal能够实现数据异构,以下图示意:
Canal的详细安装、配置与使用,请查阅官方文档 >\> 连接
表数据量大,单表3亿多。
常规定时任务迁移全量数据,时间长且对业务有损。
不停机迁移,最大化保证业务不受影响
“给在公路上跑着的车换轮胎”
总体过程大体以下:
单表数据量过大:账号单表3亿+用户惟一标识过多
业务划分不合理
使用传统的定时任务迁移,时长过长,且迁移过程当中为了保证数据一致性,须要停机维护,对用户影响较大。肯定使用canal进行迁移,对canal作充分调研与评估,与中间件及DBA共同肯定,可支持全量、以及增量同步。
在vivo海外业务开展初期,海外部分国家的数据存储在中立国新加坡机房,但随着海外国家法律合规要求愈来愈严格,特别是欧盟地区的GDPR合规要求,vivo账号应对合规要求,作了比较多的合规改造工做。
部分非欧盟地区的国家合规要求随之变化,举例澳洲当地要求知足GDPR合规要求,原有存储在新加坡机房的澳洲用户数据须要迁移至欧盟机房,总体迁移复杂度增长,其中涉及到的难点有:
Canal底层使用protobuf做为数据数据列化的方式,Canal-client在订阅到变动数据时,为null的数据会自动转换为空字符串,在ORM侧数据更新时,因判断逻辑不一致,致使最终表中数据更新为空字符串。
账号本次线上Canal-client只有单节点,但在数据迁移过程当中,因业务特性,致使数据出现了不一致的现象,示例大体以下:
出于数据一致性地考虑(结合账号业务数据未达到须要分库的必要性),账号分表在同一数据库进行,即迁移过程当中分表数据不断地进行写入,加大数据库负载的同时形成了从库读取延时。
解决方案:增长速率控制,基于业务的实际状况,配置不一样的策略,例如白天业务量大,能够适当下降写入速度,夜间业务量小,能够适当提高写入速度。
在总体数据迁移过程当中,vivo账号在client端增长了实时同步数据的简易监控手段,即基于业务表基于内存作计数。
总体监控粒度较粗,包括以上数据不一致性,在数据同步完成后,未能发现异常,致使切换至分表模式下出现了业务问题,好在逻辑数据能够经过补偿等其余手段弥补,且对线上数据影响较小。
以上是基于 Canal现有架构画出的简易图,虽然基于HA总体高可用,但细究后仍是会发现一些隐患,其中标记红色X的节点,能够视为可能出现的故障点。
基于以上可能出现的问题点,咱们能够尝试作上图中的优化。
在互联网行业,你们对“异地多活”已经耳熟能详,而数据同步是异地多活的基础,全部具有数据存储能力的组件如:数据库、缓存、MQ等,数据均可以进行同步,造成一个庞大而复杂的数据同步拓扑,相互备份对方的数据,才能作到真正意义上"异地多活”。
本逻辑不在本次讨论范围内,你们能够参阅如下文章内容,笔者我的认为讲解较为详细:http://www.tianshouzhi.com/api/tutorials/canal/404
做者:vivo 产品平台开发团队