Maxwell是一款开源产品,体积比Canal小很多。经过综合考虑,短时间内选择了麦克斯韦。从快速上手到功能支持,是一个整体支持不错的产品,也让技术研究和迭代进度相对快了很多。一般来说,如果要对比的话,基本都会把这张图拿出来(数据带有主观特征,仅供参考),因为考虑到bootstrap是刚性需求,这部分的功能性考虑也是一个重要的权衡——离开。最近在从数据库到大数据的过程中发现了Maxwell的一些问题和改进:1)Maxwell的服务管理模式目前只支持启动模式。如果想停止,只能使用手动kill的方式,比较粗暴,当然可以通过信号处理间接实现与作者的沟通。2)Maxwell的核心配置是同步对象的过滤,可以支持regex等模式。如果过滤规则比较复杂,或者后期不断调整,每次调整都需要重启Maxwell服务,没有reload-like模式。3)对于DDL变更,如果Maxwell初始化已经完成,服务已经启动,后续创建表时,Maxwell会将变更记录到`schemas`表中,维护版本变更记录,并在现有的metadatatable`tables`和`columns`中没有这些信息,会给后端服务解析表结构带来一些偏差(DDL变更配置会有对应的JSON)1.问题定位这些问题多为建议,不是个致命的问题,所以整体进度还是可以继续推进的,不过最近同步了几个大表后发现了一些数据问题。1)引导需要很长时间。查看Maxwell相关监控。整体的数据吞吐量大约是每秒800条记录,这似乎已经达到了整个同步的瓶颈。200万条数据以上的表同步需要1小时左右,相对来说是比较长的。在我们最近的测试中,如果串行初始化几千万张大表,大概需要2-3个小时,时间太长了。2)同步数据的时间字段值存在差异,在中端(maxwell规划为中端服务)和后端(Flink、Kudu为中端服务)的数据对比中也发现plannedastheback-end),和bootstrap的数据对比结果几乎不一样,说明bootstrap对数据有一些潜在的问题,所以整个事情就轮到了Maxwell的bootstrap部分。看了代码的逻辑,着实惊呆了。此问题仅发生在引导程序链接中。比如数据的time字段的值为:但是经过逻辑处理后,会计算时区,自动补上时区差。现在的问题不是初始化带来的性能危害,而是数据质量的侵入性,让数据看起来杂乱无章。对于这个问题,分析的重点是时区处理的差异。本来以为这个改动应该不大,没想到调试和环境集成真的费了很大功夫。2.Bug修正时区数据差异主要是由于datetime数据类型存在时区差异,目前差距为13小时。查看Maxwell的代码类SynchronousBootstrapper:调试后需要改动的代码逻辑作用域是基于函数setRowValues:可以修改为:修改后整个bootstrap的逻辑经过调试反复测试正常.3、性能问题的选择与修正当然,除此之外,还做了一些小的改进。第一个问题是引导程序的性能。之前好像有瓶颈,吞吐量在800左右,上不去。我做了以下改进:1)。bootstrap的一个基本原则是select*fromxxxxorderbyid;这种使用方式,如果表的数据量比较大,其实orderbypart好像是主键,这个子句会强制进行全索引扫描,但是整体效果不是全表扫描,所以我只是简单地删除逻辑中的orderby子句。整个逻辑的改造也很轻:privateResultSetgetAllRows(StringdatabaseName,StringtableName,Tabletable,StringwhereClause,if(pk!=null&&!pk.equals("")){sql+=String.format("orderby%s",pk);}2).去掉写入数据后的sleep1毫秒,我们进一步分析代码,发现bootstrap中的吞吐量瓶颈是奇怪的sleep1处理之一。初步分析,可能认为bootstrap任务会产生大量数据。对于高带宽和负载压力,可以通过sleep降低速度,整体可控。另外,bootstrap的日志统计会包含同步数据项的数量。目前这个指标值的依赖度不高,数据校验的工作会先停止Slave,然后进行数据比较性能提升和提升。3-5次,所以我们可以根据实际情况选择这部分的逻辑。在我们的通信设计中,数据是基于Slave端传输的,所以不会影响到主库。这部分改动的逻辑也很轻。,注释掉sleep(1)。publicvoidperformBootstrap(BootstrapTasktask,AbstractProducerproducer,LongcurrentSchemaID)throwsException{producer.push(row);Thread.sleep(1);++insertedRows;修改后测试对比,发现性能好很多,顶多可以6000多,同样初始化一切用了不到15分钟。这样的小改进也给我们带来了成就感。后续数据同步规模不断扩大,没有反馈数据质量问题。当然,在此基础上还有一些工作需要细化。4、后续对bootstrap方向的改进1)利用分片的思想改进bootstrap,提高数据抽取效率。对于千万级以上大表的数据抽取,可以按照区间段抽取(需要考虑数据变化和写入),目前的逻辑过于死板。privateResultSetgetAllRows(StringdatabaseName,StringtableName,Tabletable,StringwhereClause,Connectionconnection)throwsSQLException{Statementstatement=createBatchStatement(connection);Stringpk=table.getPKString();Stringsql=String.format("select*from`%s`.%s",databaseName,tableName);if(whereClause!=null&&!whereClause.equals("")){sql+=String.format("where%s",whereClause);}if(pk!=null&&!pk.equals("")){sql+=String.format("orderby%s",pk);}returnstatement.executeQuery(sql);}2)数据字典索引优化Maxwell数据字典优化,在目前的数据字典中,有些SQL执行频率很高,但是从数据库层面来看,是全表扫描,这些细节还需要进一步调整。例如下面的SQL语句:>>explainselect*frombootstrapwhereis_complete=0andclient_id='dts_hb30_130_200_maxwell003'and(started_atisnullorstarted_at<=now())orderbyisnull(started_at),started_atasc,idasc;基于业务场景的完善和调整,让我们也通过真实的场景落地,更好地拥抱开源,能够在一定程度上回馈和反哺。本文转载自微信公众号《杨建荣的学习笔记》,可通过以下二维码关注。转载本文请联系杨建荣学习笔记公众号。
