首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >中/大量数据同步技术

中/大量数据同步技术
EN

Software Engineering用户
提问于 2016-06-05 13:38:19
回答 2查看 2.7K关注 0票数 3

我为我的应用程序实现了同步(使用REST后端),它运行良好,但也存在一些问题:

  1. 块-由于我不想在同步期间覆盖用户的可能输入,所以我在同步期间阻止UI (进度覆盖)。这当然会对用户体验产生负面影响。
  2. 大小--如果数据很大,请求可能会占用很多时间,处理响应时也可能会出现内存不足的错误。

所以我在考虑如何改进这个问题。对于第2点,我想简单地分页请求,即发送我想要的条目数量和一个引用日期(例如创建日期),以简化数据库查询。

但是第1点是一个独立的问题--我为第2点所做的事情,只要用户能够在同步期间操作数据,这个数据就有可能被同步结果覆盖。例如,我可以在同步期间锁定客户端数据库,这样只有同步进程才能写入它,并对客户端操作排队,但是当这些操作试图增加一些数据时会发生什么,这些数据是通过同步而更改的,这将导致与客户端打算做的事情不同的结果。

我的应用是关于个人杂货店管理,所以要求不是超级严格,如果更新丢失或其他东西,它不是悲惨的。我正在寻找一个平衡的解决方案,这是很容易实现的,同时保持一个相当好的用户体验。

EN

回答 2

Software Engineering用户

发布于 2016-06-08 01:24:02

您所指的场景1的问题是一致性,即有两个存储相同信息的商店,并且需要它们保持一致。

在这样的分布式环境中,乐观并发可以占上风,这意味着,不需要锁定,而是允许任何东西在任何时候发生变化,并内置一种跟踪重叠的机制。

第一步,是否有真正有重叠的数据?还是您的数据集真的只是一组项目?如果是后者,那么如果您所处的情况是,任何客户端都可以添加项,并且它们可以向下复制,那么您只需要每个客户端跟踪哪些项尚未被推送。

如果可能有重叠,例如,您正在管理文档(听起来不太可能),那么您要么拥有锁定,要么允许并发更新和标记重叠作为一个问题由使用者解决。这种模式的例子如下:

  1. 软件版本控制系统,如git、mercurial、subversion等。
  2. 埃弗诺特
  3. 谷歌文档

如果您曾经使用过软件版本控制,您将认识到合并冲突和/或重叠的想法。你也有同样的问题。像Vault这样的源代码管理系统通过每个客户端将每个文件视为只读来避免这个问题,直到一个文件被“签出”,这会在所有客户端创建一个相互排斥的锁。另一方面,Git将识别冲突,如果可以合并,则合并冲突,如果不能,则强制最终用户(开发人员)手动合并。

Evernote允许我和妻子分别编辑我们的购物清单。为了最大限度地减少冲突,我们尽可能频繁地同步,但是总会有发生冲突的变化的机会,这已经发生了。Evernote简单地将相互冲突的文档版本附加到另一个上面,标记符表示存在冲突。

在并发更改很少的情况下,这种乐观的并发通常是理想的。在高度并发的事务系统中,锁定可能是一种更好的方法。

尺寸

就数据大小而言,我可以想到两个选项:

  1. 分页
  2. 流式传输

分页可能是我想要的方式,因为它通常更简单地编写代码,并且更容易跟踪您的进度,并且在某种程度上可以给您更多的控制。有了以上关于处理一致性的建议,希望分页成为一个没有问题的问题。

流也可能是你的另一种选择,而且当涉及到一致性时,也会降低风险,因为你只有一次往返。流基本上意味着改变这个数据流:

代码语言:javascript
复制
results = getResultsFromServer();
for (result in results) {
  doSomething(result)
}

至:

代码语言:javascript
复制
getResultsFromServer((result) => {
  doSomething(result)
})

在前者中,必须对整个结果集进行缓冲,以便您可以迭代它,即使您一次只能使用一个数据。在后一种情况下,一次只需要一项。我曾经为一个大型报告实现过这种方法,当客户在一个非常大的日期范围内运行它时,它会淹没我们的生产服务器。

票数 1
EN

Software Engineering用户

发布于 2016-06-07 22:38:30

我想我理解您主要关心的是输入直接绑定到本地数据库,而同步也写入本地数据库。因此,如果用户在同步期间保存了一些值,则不确定将显示哪些信息。(最后一名获胜。)

我经常为UI使用的一种解决方案是让用户编辑数据的副本,然后在他们选择保存数据后才将其保存回数据库(即使这是一个隐式的选择,比如单击输入,适用于做列表的事情)。这也使得取消操作非常容易:丢弃编辑的副本。

这样做将有助于您的同步故事,因为您可以将更改从同步持久化到本地数据库,而不会干扰用户的输入。如果它们在同步期间“保存”,则可以等到同步完成后再保存。你不需要阻止。如果您需要“正在进行的”数据持久(例如,在设备崩溃的情况下),您仍然可以保存它.就在数据库的另一个地方。

至于增加一些值并得到不同的结果,这是使用幂等操作的一个典型案例。一个简单的例子来说明:

代码语言:javascript
复制
AddQuantity(1); // result depends on previous quantity
SetQuantity(13); // result does not depend on previous quantity
                 // can be applied numerous times w/o changing result
                 // idempotent operation

当然,使用文字数字是人为的,但是13可以预先计算并在队列中携带,而不是随后通过AddQuantity方法进行计算。

当您让多个用户同步相同的项时,您将遇到并发冲突。一个用户更新和同步,而另一个用户从旧版本更新,当第二个用户同步时,他们覆盖第一个用户的更改。

在这一点上,通常的答案是某种类型的并发控制,比如带有版本号的乐观并发 (或ETags)。如果您试图更新该项目的旧版本,服务器将引发冲突。这将取决于你如何处理这场冲突。您可以向用户显示一条消息,并询问他们该做什么。(提示:他们可能总是选择用自己的版本覆盖服务器版本。)或者你可以默默地接受其中的一个版本作为权威。或者,您可以尝试应用一个算法来合并这些差异(如果适用于您的情况)。基本上,做那些能为你的应用提供最大价值的事情,以及你可以接受的权衡。

请注意,如果您正在同步用户正在编辑的内容,您就有机会检测到他们正在更改的项的更新,并显示一个横幅“此项目已被其他用户更新”。

票数 0
EN
页面原文内容由Software Engineering提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://softwareengineering.stackexchange.com/questions/321345

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档