因为历史业务数据采用mysql来存储的,其中有一张操做记录表video_log,每当用户建立、更新或者审核人员审核的时候,对应的video_log就会加一条日志,这个log表只有insert,可想而知,1个video对应多条log,一天10w video,平均统计一个video对应5条log,那么一天50w的log, 一个月50 * 30 = 1500w条记录, 一年就是1500 * 12 = 1.8亿。目前线上已经有2亿多的数据了,因为log自己不面向C端,用于查询问题的,因此能够忍受一点的延迟。 可是随着时间的积累,必然会愈来愈慢,影响效率,因而提出改造。mysql
因为log自己不是最关键的数据,可是也要求实时性高(用于实时查询问题),因此一开始的想法是核心的基础存储仍是保持不变,较老的数据迁移出去,毕竟忽然去查询一年前的操做记录的几率很小,若是忽然要查,能够走离线。设计的话,咱们只须要一个定时脚本,天天在凌晨4点左右(业务低峰期)抽数据。抽出的数据能够上报到一些离线存储(通常公司都有基于hive的数仓之类的),这样就能够保持线上的video_log的数据不会一直增加。redis
分表也是一种解决方案,相对方案一的好处就是,全部的数据都支持实时查,缺点是代码要改造了。sql
接下来就是改造代码了,得解决新老数据读写的问题。数据库
方案二的缺点比较明显,3年后咋办,继续拆表?感受始终有个历史债在那。因而咱们的目光定位到了tidb,tidb是分布式的数据库,接入了tidb,咱们就无需关心分表了,这些tidb都帮咱们作了,它会本身作节点的扩容。因为是分布式的,因此tidb的主键是无序的,这点很重要。
整个流程大概分为如下4个步骤:安全
迁移至tidb,看似很简单,其实在job脚本这里隐藏着几个坑。markdown
综合考虑数据的重复性,job重启效率性,和整个同步的效率性,我大概作出如下方案:分布式
任务分批提高效率
:首先根据处理能力和预期完成时间,先对老数据进行分批,大概分了10批,10个job去跑不一样批次的数据,互不干扰,且每次批量更新100条。记录状态,重启自动恢复到断点
:每次同步数据后记录下当前同步的位置(redis记录下当前的id),就算重启也能够从redis里拿到以前的更新位置,接着更新。避免主键冲突
:同步除了主键以外的全部字段(不一样步主键)最终经过方案三的四个切换步骤+高效率的同步脚本平稳的完成了数据的迁移ide