最终同步策略
名词解释
anchor:同步锚点,用时间戳来表示,用来表示某项记录最后同步时间
modified:修改时间,用时间戳来表示,用来表示某项纪录内容实际最后修改时间
客户端设计
每条表项包含两个用来同步用的字段:
status:用来标识记录的状态
modified:记录每条记录最后修改时间
status | 含义 |
---|---|
0 | 本地新增 |
-1 | 标记删除 |
1 | 本地更新 |
9 | 已同步 |
另外,保存一个anchor,记录服务端同步过来的时间戳;若尚未进行任何同步,anchor为-1
服务端设计
每条表项包含两个用来同步用的字段:
modified:记录每条记录最后修改时间
anchor:记录每条记录与客户端时间最后同步时间
双向同步过程
初始状态下,我们假设客户端和服务端的表各有两条数据
客户端:
id | name | phone | status | modified |
---|---|---|---|---|
1 | Ken | 18612345678 | 9 | 2 |
2 | Jim | 13888888888 | 9 | 3 |
anchor = 4
服务端:
id | name | phone | modified | anchor |
---|---|---|---|---|
1 | Ken | 18612345678 | 2 | 4 |
2 | Jim | 13888888888 | 3 | 4 |
此时,客户端与服务端的数据是完全同步好了的
Client在时间5增加1条记录
id | name | phone | status | modified |
---|---|---|---|---|
1 | Ken | 18612345678 | 9 | 2 |
2 | Jim | 13888888888 | 9 | 3 |
3 | Tim | 12345678 | 0 | 5 |
Client在时间6修改2条记录
id | name | phone | status | modified |
---|---|---|---|---|
1 | Ken | 2333333 | 1 | 6 |
2 | Jim | 010-12345678 | 1 | 6 |
3 | Tim | 12345678 | 0 | 5 |
由于还未同步,anchor仍为4
Server由于在时间8与另一客户端同步,从而修改2条记录
id | name | phone | modified | anchor |
---|---|---|---|---|
1 | Ken | 6666666666 | 7 | 8 |
2 | Jim | 77777777777 | 4 | 8 |
Client发送本地更新
客户端发送本地更新,即status为0、1或-1的表项,执行sql语句:
SELECT * FROM table WHERE status < 9
找出客户端需要同步到服务端的记录。下表中的数据是发送的同步消息
id | name | phone | status | modified |
---|---|---|---|---|
1 | Ken | 2333333 | 1 | 6 |
2 | Jim | 010-12345678 | 1 | 6 |
3 | Tim | 12345678 | 0 | 5 |
anchor = 4
Server在时间9处理同步消息
首先处理第一条数据
id | name | phone | status | modified |
---|---|---|---|---|
1 | Ken | 2333333 | 1 | 6 |
服务端收到请求后,对比客户端的modified和服务端的modified,保留modified较晚一项;在这里,保留服务器的数据,不进行修改。
然后处理第二条数据
|id |name |phone |status |modified |
|-|-|-|-|
|2 |Jim | 010-12345678 |1 |6 |
服务端收到请求后,对比客户端的modified和服务端的modified,保留modified较晚一项;在这里,保留客户端修改后的数据,并将anchor修改为此次同步时间。
最后处理第三条数据
id | name | phone | status | modified |
---|---|---|---|---|
3 | Tim | 12345678 | 0 | 5 |
如果得知status = 0,直接插入即可,并将anchor修改为此次同步时间。
服务端经过这两次操作后,数据表如下
id | name | phone | modified | anchor |
---|---|---|---|---|
1 | Ken | 6666666666 | 7 | 8 |
2 | Jim | 010-12345678 | 6 | 10 |
3 | Tim | 12345678 | 5 | 10 |
Client根据响应更新本地记录
服务端处理完数据后,还要响应客户端的请求,将所有anchor大于客户端anchor = 4的表项发送给客户端,如下
id | name | phone | modified | anchor |
---|---|---|---|---|
1 | Ken | 6666666666 | 7 | 8 |
2 | Jim | 010-12345678 | 6 | 10 |
3 | Tim | 12345678 | 5 | 10 |
并发送同步时间anchor = 9
收到响应后,客户端就开始执行UPDATE了,对每一项进行修改、将status改为9,并将anchor改为最后修改时间7。
客户端现在的数据表如下:
id | name | phone | status | modified |
---|---|---|---|---|
1 | Ken | 6666666666 | 9 | 7 |
2 | Jim | 010-12345678 | 9 | 6 |
3 | Tim | 12345678 | 9 | 5 |
并将anchor修改为anchor = 9。
客户端删除记录
逻辑删除记录:
id | name | phone | status | modified |
---|---|---|---|---|
1 | Ken | 6666666666 | -1 | 7 |
2 | Jim | 010-12345678 | 9 | 6 |
3 | Tim | 12345678 | 9 | 5 |
客户端发送消息到服务端
根据status < 9,将逻辑删除的记录发送至服务端,服务端收到消息后,将该记录移至deleted_table(相当于时光机,以后可以进行数据的恢复)表中
id | name | phone | modified | anchor |
---|---|---|---|---|
1 | Ken | 6666666666 | 7 | 12 |
服务端响应客户端的请求????
客户端收到响应
客户端直接进行物理删除
服务端删除记录
如果客户端从服务端获取的增量信息中包含删除记录的消息,则客户端直接进行物理删除