问题名称:内外网的数据库同步。
 
问题背景:目前网站已经在外网发布,全互联网的用户都能访问。 在公司的局域网内也架设了相同的网站,只有公司内部人员可以访问。数据库采用的是Mysql,开发环境为Java,采用SSH框架。
 
希望达到的目标:公司内部的编辑人员可以在内网中进行数据录入(数据量比较大,包括图片,视频等等,如果直接在外网工作网速较慢会影响工作效率,也影响互联网用户的访问速度。另外如果编辑操作失误,也不会对真实的网站带来影响,损失弥补成本较低),隔一段时间将内网中编辑添加或更新的数据同步到外网(例如每天的凌晨同步一次,避开访问高峰)。
 
问题描述:数据文件(如图片,视频等等)的同步可以通过rsync完成。但是数据库的同步存在困难。Mysql可以使用binlog来记录对数据库的所有修改,可以外网的数据库和内网的数据库都开启binlog记录修改日志,但是并不足以解决此问题。
例如,在时刻T0,内外网的所有内容都是完全一致的。从这一时刻开始,互联网的用户会对外网的网站进行操作,例如上传自己的图片,视频,更新若干资源的点击率,评分等等。而内网的编辑们也在修改内部的网站,新加入某些资源,或者对原有的资源进行修改,更新等等。外网和内网的数据库都在改变,而且两边的改变都是有价值的,需要进行merge。情景1:假设表A有3个字段:id,描述和点击数。在T0时刻,表A中的id为1的那条数据在内外网数据库中是相同的,例如内容是(1, "例子", 10)。此时如果外网用户查看了这条数据,需要增加点击数,也就是会执行一条update语句更新表A中id为1的entry,将描述设为“例子”,点击数设为“11”。如果内网中编辑修改了此数据的描述,也会执行一条update语句,更新表A中id为1的entry,将描述设为“改变了的例子”,点击数设为“10”。这两条update语句无论先执行谁后执行谁,都会导致一方的修改丢失。情景2:在T0时刻,表A中有100个对象。从T0时刻到T1时刻,互联网用户在外网数据库的表A中插入了100个对象,id为101~200,编辑们也在内网的数据库的表A中插入了100个对象,id也是101~200。而这200个对象按道理在merge后都应该保留,不过在log中它们的id是冲突的,直接执行log中的insert语句不可行。另外,表A还与其他的若干个表具有多对多或一对多关系,例如表B,C,D,那么在表A插入新对象的时候,还需要在关联表A_B, A_C, A_D中插入相关的条目,而这些条目记录的都是具体的id,因此这些关联表在内外网的数据库间也产生了冲突。像表A这样的内外网都可能同时插入或更新的数据表并不止一个,如果再算上关联表,内外网数据库间无法使用binlog来解决冲突的表数目众多。
 
当前的主流解决方案是怎样的呢?如何有效地解决此问题,达到预想的目标?

解决方案 »

  1.   


    对同一个数据UPDATE,最终只可能存在一个数据。
    update a set a.b=1;
    update a set a.b=2;结果不是1,就是2,所以你说的有问题。
      

  2.   

    情景2的id 冲突采用id的就策略一般能规避,比如外网的id递增规律是2,4,6,8....,内网id递增规律1,3,5,7,9....至于情景一的冲突,可以参考subversion的做法
      

  3.   

    情景2的id 冲突采用id奇偶策略一般能规避