2018-02-11-几种增量更新方案

问题

需要从server端同步数据到client端,server端数据量很大,并且通常需要进行分页,限制一次更新的数量,只能增量更新。

分页机制的引入会导致增量更新方案变的更加复杂,有很多地方需要注意

初步想法

一个while循环,每次更新前1分钟的数据:

1
2
3
4
5
# 伪代码
while True:
now = time.time()
sync_to_local(update_time>=now)
time.sleep(interval)

存在的问题:

如果程序崩溃,不知道上一次同步结束的时间点,无法知道下一次增量更新的时间起始点

改进1

记录下每次更新后的时间戳last_sync_timestamp,使用定时任务下一次更新时从last_sync_timestamp拉取数据

1
2
# 伪代码
sync_to_local(update_time>last_sync_timestamp)

存在问题:记录丢失
同步的时候,如果使用:update_time>last_sync_timestamp,则可能出现记录丢失的问题

改进2

改成大于等于:

1
sync_to_local(update_time>=last_sync_timestamp)

存在问题:记录重复

假设服务器存在如下记录:

id update_time
1 0001
2 0001
3 0001
4 0001
5 0002

每次获取2条记录,
第一次同步后,last_sync_timestamp=0001
本地同步到的记录为:

id update_time
1 0001
2 0001

第二次继续同步2条记录,last_sync_timestamp=0001

那么id为1,2的记录会重复获取。永远获取不到后面的记录

改进3

除了时间戳,还可在client端增加记录的唯一id,通过id+时间戳来去重。

假设服务器存在如下记录:

id update_time
1 0001
2 0002
3 0002
4 0002
5 0003
6 0003

1)第一次获取数据:
last_sync_timestamp>=0001

假设返回数据:
count=2,total=6(count表示每页记录数,total表示总共符合条件的记录数)
则本地更新内容为:

id update_time
1 0001
2 0002

本地记录下last_sync_timestamp和id,
last_sync_timestamp:0002
id:2

2)第二次获取数据
last_sync_timestamp>=0002 && id not in (2)

返回数据为:
count=2,total=4,

更新后本地数据为:

id update_time
1 0001
2 0002
3 0002
4 0002

last_sync_timestamp=0002,
id=2,3,4

4)第四次获取数据
last_sync_timestamp>=0002 && id not in (2,3,4)

返回数据:count=2,total=2
更新后本地数据为:

id update_time
1 0001
2 0001
3 0001
4 0002
5 0003
6 0003

last_sync_timestamp=0003,id=5,6

改进4

每条记录增加一个字段status,
indexed:表示记录是否已经被同步
unindexed:表示尚未同步

获取记录的时候只需要给出条件:
status==unindexed并且按照update_time排序

本地同步完成之后,更新服务器端响应记录的status即可

问题:
使用场景受限,允许客户端更新服务端状态,不适用于例如微博客户端本地增量更新的场景

参考文章:
http://blog.csdn.net/newjueqi/article/details/19114469