需要留意的是,pt-table-checksum和sync_diff_inspector都是对实体数据进行校验的工具,在数据量较大的情况下校验操作会相对缓慢,不适合在割接时间窗口中操作。在实际项目中笔者测得一个500G的数据库的完整校验耗时大约28小时。在割接时间窗口中,一般通过select max(id)或者select count(id)对数据进行简单对比。
文件存储同步
文件同步
相比于MySQL,文件作为一种非结构化的存储方式,迁移方法相对较少,也没有太多的数据一致性保障方法。与此同时,海量小文件的处理效率有限一直都是技术难题。
一般来说,文件存储的方式一般是硬盘本地存储或者基于NFS协议的存储服务,这两种存储服务中NFS存储的同步会更困难一些。单个文件的同步是简单的,将文件复制到目标空间然后再对文件计算md5校验和,只要两边的数据是一致的就行。难点在于获知文件是否有发生变化。在linux kernel中可以利用 inotify机制了解到本机对文件的修改动作。
inotify应用在启动的时候除了初始化监听和创建事件队列以外,还会在文件系统操作的函数中加入inotify hook函数以将文件系统事件通知到inotify系统中,这些都是操作系统内核中的系统调用。所以对于NFS而言inotify就失效了,因为相关调用都是本机环境中的系统调用而没有经过网络,挂载了同一个NFS的多台主机没有机制了解对方在什么时候对文件进行了操作。
所以这时候,从业务中对出现变化的文件进行记录就很有必要,因为实际上所有对文件的增、删、改都是业务所需的操作行为。所以在数据同步阶段,我们依然通过rsync或类似方法来同步数据,并且通过业务日志记录发生了变化的文件,最后在割接阶段解析业务日志,将出现过变化的文件做最后的增量同步,从而实现数据追平。
典型的组件可以参考FastDFS,FastDFS实现了类似binlog的方式,来记录每个storaged接受到哪些文件的更新,是哪种更新操作。在启动storaged之后,就可以实现自动读取其它同副本关系的storaged的数据来恢复。例如大C表示源创建,小c表示创建副本,大A表示源追加,小a标识副本追加,大D表示源删除,小d表示副本删除等等。
实际生产环境中的fastdfs binlog
当然也有一些实现了分布式锁的文件系统,例如vmware的vmfs和oracle的ocfs,可以共享文件系统数据的同时,通过锁机制来实现操作系统对文件变化的感知。
文件校验
文件的校验,这里会涉及到存储静默错误的问题。我们回忆硬盘坏道这个概念,就会发现硬盘自己也不知道某个扇区目前状态是否良好,需要专门进行扫描才能确认。一个扇区写了数据,在长久的运行中这一扇区成为了坏道导致不能读出数据,这时候应用不读取就不知道底层数据出现问题,这就是静默错误。
要解决静默错误的唯一办法是全链路数据校验:
> 在数据上传前,确认数据正常,生成校验和;
> 上传到某个存储服务之后,存储服务存储文件并且记录这个文件的校验和;
> 定期对数据进行巡检,重新计算文件校验和并且和记录值比较;
> 取出数据时,也对数据进行校验和比较,这样才能保证文件数据一致。