一切开始之前
前公司是一家小型金融公司, 整套业务系统使用微服务构建, 数据主要分散在10来台 MySQL 中, 其中包括自建的 MySQL 5.6 & 5.7 和阿里云 RDS MySQL 5.6 & 5.7. 彼时的 BI 分析使用两台主从 MySQL, 每日从业务库中使用 kettle 定时全量同步数据到 BI 主库, 通过 crontab 定时跑 SQL 生成报表, 最终在帆软平台展示.
-
上述提到了每日全量同步数据到 BI 库, 为什么不使用增量呢?
因为很多表都不具备有效的update_time
字段, 或是没有这个字段, 或是这个字段未生效. -
那为什么 BI 库要使用主从呢?
BI 数据库汇集了所有业务数据, 有一些临时的 OLAP 需求往往会从 BI 库直接查询, 经常造成锁表甚至查挂数据库; 为此, 分离了主从, 数据同步和定时任务在主库上跑, 临时查询在从库上跑, 查挂了就找运维(心疼运维一秒钟). -
除此之外, 还有什么问题?
所有的 SQL 由 BI 团队成员书写, 未经过技术人员性能优化, 经常造成 SQL 执行超时和锁表, 并且大量使用存储过程和自定义函数, 难以维护; 回溯能力较弱, 如果发现 SQL 逻辑错误, 只有少部分报表计算考虑了回溯策略, 可以重新计算过去的报表.
这种模式持续了将近两年, 虽说小问题不断, 但总归是一个低成本的解决方案.
开始
2018年中, 公司决定开始建设数据平台, 招募了一位数据平台负责人, 花费了两个月搭建 Hadoop 平台, 准备使用标准的 Hadoop 离线数仓技术取代原有的 MySQL BI 库方案. 结果, Sqoop 一个 MapReduce 抽爆了 MySQL 业务库, 这位数据平台负责人及唯一的下属也因种种原因离职.
彼时的我刚过实习期, 在做的对账系统已经趋于稳定, 并且这个项目用到 Kettle 和 Canal 这些数据同步技术, 算是跟数据沾一点儿边儿, 数据平台的交接就到了我们团队头上. 然后由于某些原因, 数据同步任务就落在了我身上.
需求
简单说, 就是实现一个 Hadoop 平台多源 MySQL 从库, 可以使用 Hive 访问. 并且, 同步不能对原有 MySQL 业务库造成压力, 还要能容忍任何合法的 MySQL 数据.
开荒之路
实习一年做的是 Java Web, 第一次接触传说中的大数据, 说实话还是挺兴奋的. 交接那几天, 彻夜地尝试 Hadoop, Hive, HDFS, Kafka, Spark, Hue 等一系列组件, 真是一种初入大观园的感觉.
那时对 Hive 的认知还停留在 "Hadoop 平台上一个类似 MySQL 的数据库", 所以接到数据同步任务的第一个想法就是: 用 Kettle / Sqoop 全量同步写入 Hive, 用 Canal 解析 Binlog 增量同步送入 Hive; 然而, Hive 不支持 update 一下令该方案陷入僵局; 查询相关资料得到的解决方案是: 单独存储 MySQL Binlog 变更, 每天将全量数据和增量数据做一次合并.
然后就是沿着这条路着手开发 Canal 的 launcher adapter (写入目标系统的组件), 发现每往 Hive 写入一条数据居然有如此大的延迟, 完全跟不上 Binlog 的产生速度; 再度陷入僵局.
读了谷歌经典的"三驾马车"论文和《SRE》后, 我才开始理解实时处理系统和批处理系统在设计理念上区别: 实时系统和批处理系统都维护请求一个队列; 对于实时系统来说, 请求队列最好时刻保持空闲, 以提供最快的响应速度; 对于批处理系统来说, 请求队列最好时刻有任务排队, 以提供最大的吞吐量.
Hive 是一个典型的批处理系统, 记录只可追加, 不能修改; 而 HBase 是一个典型的实时系统, 记录可以修改; 并且 Hive 可以通过外表读取 HBase 数据, 那么将数据直接写入 HBase, 问题就解决了.
趁这个机会, 铲掉了原有东拼西凑搭建的 Hadoop 集群, 换成了 HDP 发行版.
大方向似乎已经没问题, 而 Kettle 和 Sqoop 的写入目标并不支持 HBase, 全量同步又要换方案了, 尝试过 Spark 和直接使用 JDBC 方案, 发现一个严重的问题: 全量同步阶段, 是按表的主键增序写入的, 热点全部在 HBase 的一个 Region 上, Region Server 很容易就写挂了, 这时把主键倒序后作为 Row Key, 分散了写入热点, 并且事先预估表大小, 预定义好 Region 数量, 避免自动分裂带带来的响应时间抖动. (有些表是UUID主键, 有些是自增主键, 甚至有些表没主键.)
Canal 的 HBase Launcher Adapter 也在同步开发, 但恰逢这段时间(2018.09前后), 万年不更新的 Canal 突然开始了疯狂更新模式, 号称修复了很多 bug, 带来了性能提升, 但 Launcher Adapter API 完全被重写了, 并且 Interface 变动频繁, 前一天刚刚调试通过的 HBase Launcher Adapter, 更新一下代码, 直接无法编译. 修复 bug 的同时, 又引入了新的 bug, 比如 canal-issue-771, 导致我们线上多台服务器满载. Canal 文档很匮乏, 想深入理解 Canal 只能读源码.
除此之外, 全量同步和增量同步采用两套独立的技术方案, 在数据解析和处理过程中多少有些差异; 并且全量和增量的衔接过程完全依靠手动, 繁琐且容易出错.
经过两三个月的折腾, 兴奋感已经消失殆尽, 身心俱疲甚至开始变得有些绝望, 我甚至有点儿怀疑这个系统我真的能做出来吗?
转机
在我拼命折腾的同时, 公司领导也在联系一些商业大数据解决方案, 包括 TiDB, Data Pipeline 等, 我也都参与了评估测试, 其中 Data Pipeline 令我眼前一亮, 通过其设计文档了解到其内部工作原理, 是基于 Kafka Connect 平台的多源数据同步系统, 通过 Debezium 对 MySQL 提供全量同步和增量同步的支持. Debezium 由 Redhat 团队维护, 详细的文档和严谨的设计, 这正是我期待的方案!
数据同步方案即刻切换到 Debezium & Kafka Connect 平台, 加上之前踩过的坑, 最终的技术方案逐渐开始成型.
直到 2018.11, 新数据平台负责人(我后来的 leader, 有丰富的 Hive 数仓经验)的加入, Hadoop 集群切换到 CDH 发行版, 数据同步正式上线, 为数仓提供最底层原始数据, 整个数据平台开始走上正轨.
讲真, 如果不是当年初生牛犊不怕虎的接下这个任务, 毕业第一年也不会如此精彩.
image.png
网友评论