V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
refresh
V2EX  ›  问与答

讨论一下跨平台数据同步的问题吧

  •  
  •   refresh · 2013-06-28 23:02:57 +08:00 · 3302 次点击
    这是一个创建于 3962 天前的主题,其中的信息可能已经有所发展或是发生改变。
    例如有一个项目,有网站,网站提供restful的API,然后有iOS和android的客户端,还可能有其它客户端,所以现在要解决双向数据同步的问题。

    1. 用时间标识,但采用时间肯定是不靠谱的,因为app的时候可能是不准的
    2. 用版本号标识,改一次版本号加1。但这有一个问题,如果服务器上修改了两次,客户端也修改两次,但第一次没有同步,第二次同步的时候发现版本号是一样的。

    有什么现成的解决方案没有,你们怎么处理这个问题?
    第 1 条附言  ·  2013-06-28 23:37:54 +08:00
    另,有没有靠谱的多平台同步解决方案?或者各平台都有与restFul的同步方案,求推荐
    25 条回复    1970-01-01 08:00:00 +08:00
    zorceta
        1
    zorceta  
       2013-06-28 23:04:00 +08:00
    瞬间想起git
    swulling
        2
    swulling  
       2013-06-28 23:06:26 +08:00
    版本号,但版本号采用SHA1而不是简单的数字累加

    然后有套合并和冲突解决的机制
    refresh
        3
    refresh  
    OP
       2013-06-28 23:13:42 +08:00
    @zorceta 不用这么复杂

    @swulling 你的意思是,只要版本号不一致,以服务器为准么

    这个问题大家肯定经常遇到,现在app越来越多,同步的问题都会要面对的。
    refresh
        4
    refresh  
    OP
       2013-06-28 23:15:10 +08:00
    @swulling 每次同步的时候,要读取服务器上的所有数据,这样显得不经济,要有一个好办法解决这个问题
    horsley
        5
    horsley  
       2013-06-28 23:17:24 +08:00   ❤️ 1
    @swulling的意思其实就跟git一个道理
    管理版本号,不是简单的递增,而是用sha1等哈希算法来做,行话是数据摘要(签名)
    东西不一样,理论上签名就不会一样,所以就不存在你说的问题2,因为版本号的产生依据是数据内容
    而不是修改的次数
    时间确实不太靠谱,每个地方时钟不太一样
    不一定说是用git,但是想起git是很正常的,他的思想可以借鉴
    horsley
        6
    horsley  
       2013-06-28 23:20:33 +08:00
    @refresh git的话,以我粗略的理解,版本控制对比并不需要读取所有数据,读取的是那个版本树,版本树是由数据签名连起来的,每次的commit相当于一次快照,实际的文件内容是另外存放的,版本树上的每个节点只是索引了有哪些文件而已,有不妥的地方还望高手指正
    refresh
        7
    refresh  
    OP
       2013-06-28 23:21:57 +08:00
    @horsley 如果发现不一样,就存在一个merge的问题,有一个解决方法但不理想,就是发现不一致的时候,以服务器或者app为准。

    还有一个问题就是删除的问题,比如说数据从服务器上或者本地删除了。
    fangzhzh
        8
    fangzhzh  
       2013-06-28 23:24:24 +08:00
    给你说一个我们的思路: 客户端保存一个modtime, 此字段保存上次访问服务器时, 从服务器上取下来的时间, 下次就直接那这个时间去要数据.

    不用关心客户端的时间.
    refresh
        9
    refresh  
    OP
       2013-06-28 23:25:33 +08:00
    @horsley 实际上类似于每次同步读取索引,例如每次将一个表的id/version拉下来,再做比较,不知道我的理解对不。例如有一个todos表,里面可能有三万条数据,相当于每次同步都要将这三万条数据的id/version拖下来再比较。
    horsley
        10
    horsley  
       2013-06-28 23:28:00 +08:00
    @refresh merge的问题
    如果你了解下git,你会发现git并不是存储整份文件的,文件变更的时候只会存差异的部分 也就是diff patch,这个方法可以解决很多问题,也就是旧的版本+变化部分patch过后一定能变成新版本。当然有些时候还是要人来解决冲突,这个没办法。

    删除的问题这个有得讨论,这也是我不太放心各种同步工具的问题。
    一般是这样理解的,一种叫做同步,一种叫做备份,简单理解,同步是双向的,也就是一边删了另外一边也会删掉。备份可以是单向的,只增不删。

    当然实现起来这个删是真的删掉,还是有备份让用户可以还原,这是另外的问题
    refresh
        11
    refresh  
    OP
       2013-06-28 23:28:08 +08:00
    @fangzhzh 这也是一个不错的思路哦

    其实我们只解决单向同步的问题,就是必需以服务器或者本地的数据为准,对于双向恐怕无能为力。
    但能解决单向的问题也不错,我觉得双向确实比较难。
    horsley
        12
    horsley  
       2013-06-28 23:33:50 +08:00
    @refresh @fangzhzh 始终基于时间也还是不靠谱,服务器将来如果要分布式怎么办,时间能确保绝对同步么
    fangzhzh
        13
    fangzhzh  
       2013-06-28 23:34:53 +08:00
    @refresh 没错. 我的解决方案是生产环境使用的, 经过大数据量验证, 简单优雅.
    解决了数据总要全部同步的问题, 删除在这个方案上也可以轻易做到, 比如标志位.

    如果有了用户数据库, 加上一个用户中间件之后, 为每个用户维护一个列表, 个性化也解决了.
    @horsley 楼主的需求,一看就比较像新闻类的内容, 涉及的操作就是 新闻的增删改. 你这方案over skill了.
    fangzhzh
        14
    fangzhzh  
       2013-06-28 23:36:05 +08:00
    @horsley
    两个方案,
    1 时间服务器. 都来这里问时间.
    2 服务器一般都会有时钟同步. UST时间即可.
    refresh
        15
    refresh  
    OP
       2013-06-28 23:36:10 +08:00
    @horsley 我觉得结合@fangzhzh 所说的服务器时间与版本,可能能解决大部分的问题。我现在想用一个相对比较简单的方案来解决问题,不希望太复杂。

    删除的问题,客户端删除并不做真正的删除,而是加上一个标题,同步的时候先让服务器删除,确定服务器删除再删除本地。

    服务器删除可以直接删除,客户端在同步的时候,如果发现本地有数据(非新建的情况),而服务器上没有这条数据,表示服务器已经被删除。

    这种双向还不是真正的删除,同一条数据,客户端和服务器端都发生改变,真正的双向应该以最后更新的数据为准。但上面的讨论解决方案,都必需以服务器或者客户端的一个版本为准,而不是以时间为谁。

    例如:服务器上的数据3:00 pm被修改,客户端的数据4:00pm被修改,数据之前都没有同步,这时候同步,应该是客户端覆盖服务器端的。但如果按版本号不同来同步数据,可能就是用服务器覆盖本地的了(也可能反之,但无法智能识别)。
    refresh
        16
    refresh  
    OP
       2013-06-28 23:44:52 +08:00
    @fangzhzh 能说一下你们的实现逻辑么,仅用服务器时间解决问题,用版本号不?
    fangzhzh
        17
    fangzhzh  
       2013-06-28 23:44:54 +08:00
    @horsley 不好意思, 脑残了, 是UTC时间
    laiwei
        18
    laiwei  
       2013-06-28 23:46:03 +08:00 via Android   ❤️ 1
    @horsley 你确定git 存储的是 旧版本 + diff,然后生成新版本?

    我记得这个是svn的工作原理吧!

    git存储的都是整个文件,只不过如果两次commit中没有发生任何变化的文件始终只有一份。(发生变化的话才存两份)
    horsley
        19
    horsley  
       2013-06-28 23:59:01 +08:00
    @laiwei 查了一下好像是记错了……
    refresh
        20
    refresh  
    OP
       2013-06-29 00:02:17 +08:00
    @fangzhzh 用服务器时间有一个问题,假如客户端某一次更新,网络无法链接,取不到服务器的时间,在线的时候,如何处理?
    fangzhzh
        21
    fangzhzh  
       2013-06-29 00:08:50 +08:00
    @refresh 没更新到,modtime不变化啊
    fangzhzh
        22
    fangzhzh  
       2013-06-29 00:10:06 +08:00
    @fangzhzh 其实也用版本号, 不过版本号解释稍微复杂了些. 版本号是和具体的产品应用有关系的, 没有通用的. 我们的版本号,就是为了判定过期新闻.
    refresh
        23
    refresh  
    OP
       2013-06-29 00:28:03 +08:00 via iPad
    @fangzhzh 新闻类是单向同步,客户端不改数据
    zhigang1992
        24
    zhigang1992  
       2013-06-29 22:33:49 +08:00
    全部重新获取,有ETag呀。。。
    refresh
        25
    refresh  
    OP
       2013-06-30 13:24:38 +08:00
    @zhigang1992 ETag只适合于RSS或者图片资源类,不适合restFul API吧
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   2389 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 30ms · UTC 07:31 · PVG 15:31 · LAX 00:31 · JFK 03:31
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.