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

2013-06-28 23:02:57 +08:00
 refresh
例如有一个项目,有网站,网站提供restful的API,然后有iOS和android的客户端,还可能有其它客户端,所以现在要解决双向数据同步的问题。

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

有什么现成的解决方案没有,你们怎么处理这个问题?
3420 次点击
所在节点    问与答
25 条回复
zorceta
2013-06-28 23:04:00 +08:00
瞬间想起git
swulling
2013-06-28 23:06:26 +08:00
版本号,但版本号采用SHA1而不是简单的数字累加

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

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

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

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

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

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

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

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

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

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

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

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

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

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

git存储的都是整个文件,只不过如果两次commit中没有发生任何变化的文件始终只有一份。(发生变化的话才存两份)
horsley
2013-06-28 23:59:01 +08:00
@laiwei 查了一下好像是记错了……
refresh
2013-06-29 00:02:17 +08:00
@fangzhzh 用服务器时间有一个问题,假如客户端某一次更新,网络无法链接,取不到服务器的时间,在线的时候,如何处理?

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

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

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

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

© 2021 V2EX