问题
需要从server端同步数据到client端,server端数据量很大,并且通常需要进行分页,限制一次更新的数量,只能增量更新。
分页机制的引入会导致增量更新方案变的更加复杂,有很多地方需要注意
初步想法
一个while循环,每次更新前1分钟的数据:
1 | # 伪代码 |
存在的问题:
如果程序崩溃,不知道上一次同步结束的时间点,无法知道下一次增量更新的时间起始点
改进1
记录下每次更新后的时间戳last_sync_timestamp,使用定时任务下一次更新时从last_sync_timestamp拉取数据
1 | # 伪代码 |
存在问题:记录丢失
同步的时候,如果使用: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即可
问题:
使用场景受限,允许客户端更新服务端状态,不适用于例如微博客户端本地增量更新的场景