程序想要支持离线使用?应该怎么实现云端实时同步?

241 天前
 zyxk
程序想要支持离线使用?应该怎么实现相关技术?

比如一个最简单的单人记账软件,想要实现云端实时同步,客户端离线时时也可以使用全功能,

我是这样想的,软件使用本地数据库 Sqlite 实现全部功能,每个表都要增加一个时间检验,

因为网页端可能修改数据,客户端离线时也可能修改了数据,

所以每次客户端启动时逐行判断检验字段实现同步数据,(数据量少时可以,数据量大的软件怎么实现呢)

之后客户端正常在线,WebSocket 连接服务器,添加或更新数据后,ws 通知服务端更新?

但是感觉这样实现后不太严谨?请问这种需要应该怎么实现?请教各位
2660 次点击
所在节点    程序员
26 条回复
dode
241 天前
需要多个客户端数据合并吗
zyxk
241 天前
@dode 应该是不需要的,客户端只登录一个。
cnoder
241 天前
版本控制要重新设计,有网了再同步主要就是处理多端的版本冲突,另外最好增量校验
Mithril
241 天前
同步不是问题,如何解决冲突才是问题。没有什么办法可以完美的自动解决冲突。比如你说的办法,如果本地时间不准就可能丢数据。
所以分布式代码管理使用分支,和并请求等等措施,让你手动解决冲突。
OneNote 等笔记也会在有冲突的时候通知你。

最简单的办法,压根就不提供这样的功能。而是在客户端允许用户手动把数据上传更新到服务器,或者手动将数据同步回客户端本地。你不更新就一直用本地数据。
然后在同步的时候提醒用户数据可能有冲突,让他自己选用哪个。只要你在服务器保留每个版本的完整快照,不会让客户丢数据就可以了。

另外记账软件和笔记等等还是不一样的。你可以把它当成一个 Log 收集系统。每条记录都相对独立,而且一旦生成就很少修改,因而也很少产生冲突。你可以将每一次修改都视为创建一条不可变记录,只不过修改时将旧的记录标记为不可用,删除也是如此。
这样就算同步彻底乱套了,你也就只会多数据,而不会丢。
dode
241 天前
联网后直接覆盖云端啊,要啥字段版本控制,做好表的设计,哪些数据要同步,感觉增量备份比较好,
大型表,不要修改历史数据
timethinker
241 天前
记录一下最后同步时间,注意这里的时间最好是一个逻辑序号,每同步一次在服务端就自增一次。

客户端拿到这个序号以后,在本地的任何操作,具体表现在存储上都关联上这个序号,这样当你下次同步的时候,就可以查询出所有跟这个序号相关联的数据变动,然后把这些数据+序号提交到服务器。

当不同的终端/客户端开始进行同步时,服务端就能够取出这个序号,比较一下当前最后同步序号,这样就能知道不同客户端在同步上的先后顺序。

在技术上有很多种方法来做,上面的序号是一种,还有一种就是写日志,通过快照+重放来实现同步。当然技术只是一方面,如何实现同步的逻辑流程取决于具体的场景,更重要的是你如何处理复杂的边界情况。
zyxk
241 天前
@Mithril @timethinker 感谢各位 非笔记类软件, 更类似于记账软件,这样应该不太存在冲突问题,只要保留最新的就可以了

@cnoder @dode 感谢,麻烦问下,增量检验或增量备份应该要怎么实现?我的理解是:假如离线,本地修改了后,本地更新数据库,同时标记或记录一下修改的数据 id ,在联网时只同步这些标记的数据吗?
iosyyy
241 天前
可以考虑 Myers 算法
当数据量大的时候直接让他选择其中一个版本不同意合并
deeridea
241 天前
@zyxk 其实 本地录入数据和 线上录入数据 使用不同表进行记录也是个方法,然后接口呈现时进行数据合并,本地端联网时 和云端互换数据 云端下行更新 cloud 表 本地上行更新 local 表
iOCZ
241 天前
记录一下同步时间,每条记录增加 update 时间和同步标志。同步的时候先拉取上次同步后的新修改数据。如果记录更新时间比现在新就覆盖,否则就丢弃并标记为未同步。筛选未同步的记录,然后上传到服务器,replace into 到表里。
tyzandhr
241 天前
直接用 firebase realtime database
bxb100
241 天前
CRDT
totoro52
241 天前
@dode #5 那么问题来了,假设我在 A 电脑上修改了记录,并且增加了很多数据, 然后上传云端,此时我在 B 电脑也写入了很多数据, 然后这个时候联网了,开始同步,会发生什么事
codehz
241 天前
这不直接 CRDT 吗(
不过如果模型简单的话,可以直接记录修改然后重放
dode
241 天前
@totoro52 楼主说不涉及多个客户端数据合并吧
mayne95
241 天前
有没有可能记账软件并不需要服务端,p2p 多端 CRDT 同步就行了。https://github.com/vlcn-io/cr-sqlite
omerg
240 天前
@zyxk #7 离线修改之后,将修改的记录标记为 dirty ,在线时将 dirty 记录上传。
zeusho871
240 天前
git......(#误
horizon
240 天前
sqlite 支持 wasm ,直接强行同步 sqlite ?
NUT
240 天前
CRDT 不合适, 记账软件,你不能给他把冲突的给干掉。 还是实现一套类似 binlog 的模式,做日志同步。 不过服务器的节点为主节点, 以服务器的变更为准。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/972638

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX