(1)多线程管道实现
在精卫平台应用的早期,数据的同步均是采用单线程管道任务模式,即如
图5-12中对binlog进行单线程的处理。随着业务的发展,需要同步的数据量越来越大,单纯的单线程管道任务已经成为系统的瓶颈,后来开发了对多线程管道任务的支持(如图5-14所示)。
但多线程管道就会带来数据同步的顺序问题。在对binlog数据进行多线程并行处理后,就不能保证在源数据库中执行的SQL语句在目标数据库的顺序一致,这样在某些业务场景中一定会出现数据不一致性的问题。对于这个问题,目前精卫中提供的解决思路是保证同一条记录或针对同一分库表发生的数据同步按照顺序执行。
如果最后发送到分布式数据层的SQL语句中没有分库键,则通过对“库名+表名+主键值”哈希后对线程数取模,这样就能让同一条记录的数据同步事件处理都会在同一线程中顺序执行,保证了该记录多次变更的顺序性,但是不保证不同记录间的顺序。如果SQL语句中有分库键,则通过“库名+分库键值”哈希后对线程数取模,效果是保证不同逻辑表针对相同分库逻辑的记录变化顺序。
(2)数据的安全
凡是牵涉数据的操作,数据的安全一定是最重要的。如何保证在分布式环境下同步任务效率最大化,同时保证服务的稳定和数据的安全,是很多此类平台精益求精、力求突破的方向。
平台稳定性保障。为了保证同步任务执行的效率最大化,同时互相不会因为资源会抢占或某些同步任务的异常对其他任务造成影响,在精卫的系统设计中,支持多个服务节点作为任务执行的集群,通过统一的任务调度系统(Zookeeper集群),将任务分配到集群中的各节点并行执行。
为了保证任务间不会因为同步任务性能或异常造成互相的干扰,采用了每个同步任务都是独立Java进程的方式运行,出现异常该任务自动终止。任务调度系统会定期轮询任务列表,发现任务缺少立即抢占式启动该任务。
心跳+报警。运行集群与ZooKeeper采用定时心跳的方式,将集群节点的运行状态以及任务完成的位点(即目前同步任务处理binlog的进度信息)信息同步到Zookeeper上,如果心跳信息异常或位点时间落后过大则立即报警。在抽取器和分发器发生任何错误复制任务立即转变成STANDBY状态,集群中其他机器上的服务在感知后会立即将自己启动,继续执行前一复制任务。
MySQL主备切换。利用比对主备数据库的状态信息,通过以下顺序,采用手工的方式处理MySQL出现主备切换时进行同步任务的恢复:
1)查看新主库的当前位点Show master status,获取到PA状态。
2)查看老主库拉去新主库的位置Show slave status,获取到PR状态。
3)如果PR>PA,直接用新主库的位点PA切换到新主库上读取。
如果希望通过自动化的方式,实现的思路则可利用binlog里的serverId和时间戳,发现dump的binlog中的serverId发生变化记录变化时间戳,然后在给定的MySQL服务器中查找到有同样变化的数据库,根据探测到的serverId发生变化的时间戳进行回溯,在新的机器符合条件的位点进行dump。
MySQL异常挂掉。利用数据库上binlog文件修改时间,按照以下顺序采取手工的方式进行整个文件回溯:
1)在数据库所在的服务器上找到服务挂掉的时间点。
2)到新的主机上查看找到服务挂掉时间点之前最近的binlog文件。
3)从这个文件的位点开始进行回溯。
如果希望通过自动化的方式自动进行恢复,可同样借鉴MySQL主备切换中提到的自动化实现思路。
(3)友好的用户自服务接入体验
精卫平台是整个电商业务实现数据实时同步复制的统一平台,负责来自上千个不同应用的需求,如果每一个应用的接入都需要平台的技术人员给予入门的培训和支持都是非常大的工作量,也会影响到前端应用的用户体验。所以提供一个用户体验友好,自带常用功能的平台,能针对大部分的业务需求可以让应用方在界面上通过配置的方式就能实现,大大降低接入开发成本。
如图5-15所示,精卫平台给应用方客户提供了Web的配置界面,可让用户针对需要同步的数据源进行设置,并对数据同步的事件类型(增、删、改)和是否进行分表以及分库分表键列等进行设置。
精卫平台的数据库分发器支持一些高级功能,如字段过滤、字段映射、action转换等,如果自带功能不满足需求,可以上传包含自己的业务逻辑的过滤代码。这些功能的使用也提供了界面的方式,让用户对源数据库表中的字段如何映射到目标数据库表进行设置(如图5-16所示)。
图5-16 精卫提供的自服务体验提升数据同步服务接入效率
正是有了这样简单易用的用户体验,使得精卫平台在应用的接入效率和用户满意度上都有非常不错的表现。