根据时间戳,增量同步数据的解决办法

 由于markdown的样式太丑了,懒得再调整了,我另外再贴一个github的博客该文的 github链接

前言

最近在工作中遇到一个比较棘手的问题,客户端从服务端同步数据的问题。
背景简介:客户端有N个,客户端上的同步时间,各不相同。同步的时候,是一次获取10条数据,多批次获取。即分页获取。
在代码中存在两种同步的方式:

  1. 全量同步。同步过程是从服务端拉取全部的数据;依赖具有唯一约束ID来实现同步。只适用于数据量小的表,浪费网络流量。
  2. 增量同步。从服务器拉取大于客户端最新时间的数据;依赖于时间戳,问题时间戳不唯一存在相同时间点下面多条数据,会出现数据遗漏,也会重复拉取数据,浪费网络流量。

本文的所使用到的解决办法,就是结合了唯一ID时间戳,两个入参来做增量同步。本文也只做逻辑层面的说明。

模拟场景

表结构:ID 具有唯一约束, Name 姓名, UpdateTime 更新时间;现在问题的关键是ID为3,4,这两条时间点相同的数据。
假如一次只能同步一条数据,如何同步完ID 2后,再同步 ID 3。

ID Name UpdateTime
1 张三 2018-11-10
2 李四 2018-12-10
3 王五 2018-12-10
4 赵六 2018-11-20
5 金七 2018-11-30

解决思路

生成新的唯一标识

通过 UpdateTime 和 ID 这两种数据,通过某种运算,生成新的数。而这个新的数具备可排序唯一;同时还要携带有IDUpdateTime的信息。
简单表述就是,具有一个函数f: f(可排序A,可排序唯一B) = 可排序唯一C 。 C 的唯一解是 A和B。RSA加密算法

我想出了一个方法,也是生活中比较常用的方法:

  1. 先把 UpdateTime 转变成数字。如: 字符串 2018-12-10 -> 数字 20181210;
  2. 然后 UpdateTime 乘以权重,这个权重必须大于ID的可能最大值。如: 20181210 * 100 = 2018121000,Max(ID)<999
  3. 然后再把第二部的结果,加上唯一键ID。如: 2018121000 + 3 = 2018121003。

这个时候,2018121003 这个数,既包含了UpdateTimeID的信息,又具有可排序唯一性。用它作为增量更新的判断点,是再好不过的了。
但是它具有很大的缺点:数字太大了,时间转化成数字,目前还是用的是级别,如果换成毫秒级别呢。还有ID可能的最大值也够大了,如果是int64那就更没得搞了。

这个方法理论上可行,实际中不可用基本不可行,除非找到一种非常好的函数f;
PS: 我的直觉告诉我: 极可能存在这种函数,既满足我的需要,又可以克服数字很大这个问题。只是我目前不知道。

数据库表修改(不推荐)

修改数据内容

修改数据内容,使 UpdateTime 数据值唯一。缺点也比较明显:

  1. 脚本操作数据的情况下,或者直接sql更新。可能会,造成时间不唯一;
  2. 只是适用在数据量小,系统操作频率小的情况下。因为毫秒级别的时间,在绝大多数软件系统中,可以认为是唯一;
  3. 尤其是老旧项目,历史遗留数据如何处理。

增加字段

还有一种办法,就是在数据库中,增加一个新的字段,专门用来同步数据的时候使用。
比方说,增加字段 

关键字:
50000+
5万行代码练就真实本领
17年
创办于2008年老牌培训机构
1000+
合作企业
98%
就业率

联系我们

电话咨询

0532-85025005

扫码添加微信