程序想要支持离线使用?应该怎么实现云端实时同步? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
zyxk
0.02D
V2EX    程序员

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

  •  
  •   zyxk 2023-09-11 10:17:24 +08:00 3808 次点击
    这是一个创建于 811 天前的主题,其中的信息可能已经有所发展或是发生改变。
    程序想要支持离线使用?应该怎么实现相关技术?

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

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

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

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

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

    但是感觉这样实现后不太严谨?请问这种需要应该怎么实现?请教各位
    第 1 条附言    2023-09-11 11:43:33 +08:00
    通常做法是自行实现数据对比或增量同步吗?

    使用的 Golang , 有没有一种库可以实现本地数据和云端数据的同步?
    26 条回复    2023-09-14 18:32:13 +08:00
    dode
        1
    dode  
       2023-09-11 10:28:26 +08:00
    需要多个客户端数据合并吗
    zyxk
        2
    zyxk  
    OP
       2023-09-11 10:31:49 +08:00
    @dode 应该是不需要的,客户端只登录一个。
    cnoder
        3
    cnoder  
       2023-09-11 10:34:44 +08:00
    版本控制要重新设计,有网了再同步主要就是处理多端的版本冲突,另外最好增量校验
    Mithril
        4
    Mithril  
       2023-09-11 10:34:58 +08:00
    同步不是问题,如何解决冲突才是问题。没有什么办法可以完美的自动解决冲突。比如你说的办法,如果本地时间不准就可能丢数据。
    所以分布式代码管理使用分支,和并请求等等措施,让你手动解决冲突。
    OneNote 等笔记也会在有冲突的时候通知你。

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

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

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

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

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

    @cnoder @dode 感谢,麻烦问下,增量检验或增量备份应该要怎么实现?我的理解是:假如离线,本地修改了后,本地更新数据库,同时标记或记录一下修改的数据 id ,在联网时只同步这些标记的数据吗?
    iosyyy
        8
    iosyyy  
       2023-09-11 11:19:38 +08:00
    可以考虑 Myers 算法
    当数据量大的时候直接让他选择其中一个版本不同意合并
    deeridea
        9
    deeridea  
       2023-09-11 11:51:13 +08:00
    @zyxk 其实 本地录入数据和 线上录入数据 使用不同表进行记录也是个方法,然后接口呈现时进行数据合并,本地端联网时 和云端互换数据 云端下行更新 cloud 表 本地上行更新 local 表
    iOCZ
        10
    iOCZ  
       2023-09-11 12:02:26 +08:00
    记录一下同步时间,每条记录增加 update 时间和同步标志。同步的时候先拉取上次同步后的新修改数据。如果记录更新时间比现在新就覆盖,否则就丢弃并标记为未同步。筛选未同步的记录,然后上传到服务器,replace into 到表里。
    tyzandhr
        11
    tyzandhr  
       2023-09-11 12:07:51 +08:00 via Android
    直接用 firebase realtime database
    bxb100
        12
    bxb100  
       2023-09-11 13:39:09 +08:00
    CRDT
    MIUIOS
        13
    MIUIOS  
       2023-09-11 13:52:28 +08:00
    @dode #5 那么问题来了,假设我在 A 电脑上修改了记录,并且增加了很多数据, 然后上传云端,此时我在 B 电脑也写入了很多数据, 然后这个时候联网了,开始同步,会发生什么事
    codehz
        14
    codehz  
       2023-09-11 15:03:37 +08:00   1
    这不直接 CRDT 吗(
    不过如果模型简单的话,可以直接记录修改然后重放
    dode
        15
    dode  
       2023-09-11 15:10:43 +08:00
    @totoro52 楼主说不涉及多个客户端数据合并吧
    mayne95
        16
    mayne95  
       2023-09-11 15:17:49 +08:00
    有没有可能记账软件并不需要服务端,p2p 多端 CRDT 同步就行了。https://github.com/vlcn-io/cr-sqlite
    omerg
        17
    omerg  
       2023-09-11 16:09:35 +08:00
    @zyxk #7 离线修改之后,将修改的记录标记为 dirty ,在线时将 dirty 记录上传。
    zeusho871
        18
    zeusho871  
       2023-09-11 16:11:10 +08:00 via Android
    git......(#误
    horizon
        19
    horizon  
       2023-09-11 19:14:12 +08:00
    sqlite 支持 wasm ,直接强行同步 sqlite ?
    NUT
        20
    NUT  
       2023-09-11 19:18:12 +08:00
    CRDT 不合适, 记账软件,你不能给他把冲突的给干掉。 还是实现一套类似 binlog 的模式,做日志同步。 不过服务器的节点为主节点, 以服务器的变更为准。
    butanediol2d
        21
    butanediol2d  
       2023-09-11 19:54:06 +08:00
    @NUT #20 CRDT 不就是没有冲突吗?
    KagurazakaNyaa
        22
    KagurazakaNyaa  
       2023-09-11 23:57:13 +08:00
    直接用文本存储+git 版本控制得了
    AItsuki
        23
    AItsuki  
       2023-09-12 02:27:46 +08:00
    这种应用实现难度在前端而不是后端,前端要设计复刻一套后端的业务逻辑,然后进行同步表。
    同步的逻辑基本都是前端处理,后端只做数据版本校验(类似乐观锁的那种版本),符合规则的就入库。如果多设备同步出现冲突,简单的方案是谁先同步谁胜出。总的来说还是比较复杂的,所以我更推荐的是实时数据库。

    例如 realm ,couchdb 等。或者使用云服务,例如 google 的 firebase 的实时数据库,aws 和 azure 我记得也有,忘了叫啥。
    shenyuzhi
        24
    shenyuzhi  
       2023-09-12 12:04:43 +08:00
    最大的坑在于冲突了怎么办。
    如果需要解决冲突,这个问题会非常复杂。
    如果不需要解决冲突,那就简单了,根本不需要自己写服务器端程序,直接对接各种云存储就行了。本地用 sqlite ,每隔一段时间备份到云存储。
    SenLief
        25
    SenLief  
       2023-09-12 17:29:26 +08:00 via iPhone
    同步的解决要远大于记账类软件的开发的。最难得问题就是冲突如何处理?多端同步如何识别相同的内容?
    NUT
        26
    NUT  
       2023-09-14 18:32:13 +08:00
    @butanediol2d CRDT 是用最大可能进行处理冲突。 而不是没有冲突。 可以查一下。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2542 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 27ms UTC 10:43 PVG 18:43 LAX 02:43 JFK 05:43
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86