/migration

migration a user's all data to anything others databases

Primary LanguagePHPGNU General Public License v3.0GPL-3.0

#MIGRATION

##项目成立背景: 希望单独导出正式库的某个用户的id到指定的数据库。所以migration项目成立。

##migration项目架构 通过消息队列,产生多进程模型。使用多进程来提高并发的能力,使用supurvisor来维护worker进程开机自启动,被意外kill掉之后再生 。利用task table 和sub task table来动态的描述任务的进度情况, 具体见下图migration.png

##项目遇到的问题 1,表结构描述问题。独立的数据转移项目,不能写死表的结构,如果表的结构写死了。一旦有表更新就会出现迁移问题。 2,表间关系描述问题。 3. 由于消息队列没有描述具体任务的完成程度,所以要用task table以及sub sub task table来记录执行情况。

##项目划分模块 1.接收器模块。主要负责接受用户的请求,根据请求划分具体task,然后根据taskID生产出sub task,将sub task打包成message ,推到redis message queue中。 2.消费者模块,主要功能负责从redis message queue中取消息,之后调用worker执行具体的迁移工作。 3.worker模块,主要负责迁移数据表的迁移工作。如果出现意外情况,写一条失败类型的数据到sub task table中。为后面的重 新迁移以及与用户进行交互工作,如果成功,写一条成功的数据到sub task table中,表明数据已经转移成功。其中难点之一是 遇到数据量大的时候可能会出现内存不够用的情况出现。 4.查询进度模块。主要负责接受client的请求,将进度情况反馈给用户。如果出现错误,对用户进行提示。(方案整理中), 如果全部的表的数据迁移成功,根据用户请求的参数。决定是否要去删除原型的数据。

###接收器模块 3.生成一个task ID,(以后作为让用户查看任务的进度使用),在task table中插入相关信息。 4.根据请求参数,智能过滤无效参数,根据用户的给的参数,去命中task sets,如果命中的任务是单任务(就一张表),则打包 成message放到队列里面,,如果命中的复杂任务,则根据投票累加算法,选出优先级和表之间的对应关系打包,放到消息队列 中,其中最有挑战性的是,设计合理的命中算法,一旦一个task被命中,其他表转移请求,就不会再打包同一个task到消息队 列中。拆分出来的子任务,会产生一个sub task ID ,会一起放入到message当中。 5.分发完任务之后,

###消费者模块 1.接受消息,根据任务类型,是否跨服务器,是否存在关联关系,下发任务到worker ###worker模块 1.根据消费者下发的参数,获取远程数据库的的某个表的结构,将查出来的结构放到redis缓存中(以便下次重复使用,超期时间为一个星期), 2.编写算法解析下发参数,根据表间执行顺序,去旧表取数据(采用分批100条每次的循环分批取,反正内存不够用,用完这个注销这个变量) 。插入新表,保存旧表和新表的对应ID,按照表间优先级,同样重复执行。如果遇到有需要替换id的,则根据之前的旧表和新表的对应 ID的数据,将旧数据替换成新数据,再插入数据。同理,执行到最后,如果找不到替换的id,则将待替换的id变为null,如果出现意外情况 ,进行事务回滚,只有全部表都被插入成功之后,才提交事务,如果用户参数需要删除原来的数据,则在delete_table中插入一条消息 (为了保证转移之后数据完全正确,旧有的数据要在一个星期之后才会安全彻底删除),作为删除消息队列的message.有一个专门删除 旧数据的队列。 3.队列执行完了之后,根据message中sub task id ,找到对应的表记录,更新任务状态,只有任务的总数和全部完成的子任务的总数对应了 ,才算是任务全部完成 ###清除数据模块 1.读取delete table中的数据,根据delete table中的数据,删除对应的数据

###依赖

  • redis-server
  • supervisord
  • php
  • nginx | aparche

###安装 安装好上述依赖,请配置migration/application/config.php文件,设置正确的配置,具体信息参考config.php

###自动表结构的的获取 通常表结构的获取是从原数据库中获取,如果原库和目的数据库表结构不一致,有可能导致该表获取不到数据。 可以修改配置文件,将获取原数据的表结构从目的库中获取

##注意 巭孬嫑乱动

如果需要跨服转移数据,请使用数据的公网ip,否则将出现部分表的数据不会被导入 生产环境数据库集群(127.0.0.1,...)。 目前只支持从正式库导入到测试库(包括本地),不支持从测试库或者本地库导入到正式数据库,理论上是可以做到的

免责申明:除非你懂这里的规则,否则不要玩弄数据,出现问题概不负责,到时候请不要问我

###联系方式 williamchu 154893323@qq.com