实时协作中如何保存


10

我希望多个用户编辑同一文档。我面临的问题是,当新用户加入时,他可能会看到过时的文档。如何确保新用户获得最新更改?

我想到的一些解决方案:

  • 保存所有更改。我不喜欢这种解决方案,因为它会减慢UI速度并增加db的负载。

  • 当新用户加入时,触发所有其他客户端上的保存。保存其他客户端后,加载文档。与此可能仍然存在不一致。

任何其他建议都会有所帮助。

更新:在研究了建议的解决方案Google Realtime API之后,我发现:

  1. 您的应用程序用户必须具有Google云端硬盘,并允许您访问其驱动器。这最多可能会导致尴尬的UI流程,或阻止没有Google云端硬盘的用户使用实时功能。

  2. 必须将您完成的所有共享设置复制到Google文档中。

更新2:为达到目标,我选择了Google的Firebase


为什么新用户和已经在活动中的用户在编辑/查看同一文档时会有区别?
安迪

@Andy我现在正在做的是通过套接字广播用户所做的所有更改。这些更改将为已打开浏览器但未立即保存到数据库的用户更新UI。因此,我遇到一种情况,当新用户加入时,他从数据库中加载文档,而他看不到所有尚未保存的最新更改。
dev.e.loper

1
如果您已经发送了更改,并且想要保持与现在相同的行为,则可以要求其中一个客户端向新客户端发送最后一个视图,或者您可以在服务器上拥有一个虚拟客户端,该虚拟客户端可以获取所有更改,并且新客户端加入时发送最新的信息。查看它。
Dainius 2013年

Answers:


14

Google云端硬碟

如果您要制作自己的google docs版本,建议您看一下Google Realtime API。Google最近发布了此版本,其目的是允许其他开发人员使用与实时协作相同的工具。这将使您节省开发时间并更快地获得可用的产品。

您可以轻松地定期获取文档中的数据并将其推送到数据库中,或者让数据库本身成为交换的“参与者”,只需侦听并记录所有更改即可。它还允许用户定义自己的数据结构,这些数据结构随后可在实时API中使用,因此您可以随意扩展它。

非Google云端硬碟

因此,根据您的研究,Google Drive不是一个选择。很好,但这会变得更困难,并且可能无法正常运行,具体取决于您投入的数量。

这是用来解决此问题的一般策略

  1. 让服务器作为通信多路复用器。每个人都与服务器对话,然后服务器将该信息发送给其他所有人。这样,服务器将始终具有文档的最新视图。

  2. 查找用于冲突解决的第三方算法/模块。解决冲突很困难,而且仍然不完美。单独执行此操作很容易将项目范围扩大到太大。如果您不能使用第三方算法,我建议您只允许一个用户编辑某个时间段,这样,该用户必须在编辑某个区域之前获得一把锁,否则可能会破坏另一位用户的工作,这会导致会变得很旧,很快。

  3. 当新用户加入时,向他们提供最新文档并自动开始将命令流式传输给他们。服务器具有最新视图,因此可以自动将其弹出。

  4. 一定时间间隔备份到数据库。确定您要备份的频率(每5分钟一次,也许每50次更改一次。)这使您可以维护所需的备份。

问题:这不是一个完美的解决方案,因此您可能会遇到一些问题。

  1. 服务器的吞吐量可能会成为性能瓶颈

  2. 太多的人读/写可能会使服务器超载

  3. 如果丢失一条消息,人们可能会变得不同步,因此您可能需要确保定期进行同步。这意味着要再次发送整个消息,这可能会很昂贵,但否则人们可能没有相同的文档并且不知道。


是的,更改将广播到所有客户端,并且它们在浏览器上具有其(希望是相同的)版本。听起来您是在说,要对每个操作更新文档,这是一种方法吗?
dev.e.loper

或至少具有常规的“同步”时间范围,其中文档的当前状态在后台传输出去,以确保每个人都在同一页面上。频率取决于人们更改文档的速度。这样,您已经拥有了一种确定的发送给新人们的方法,并且能够确保发送给您的消息不会造成太大的差异。
Ampt入渗

1
+1。不要让生活困难。Google无需重新发明轮子就能做到这一点。
Neil

Google Realtime是否保存到Google云端硬盘?我想保存到数据库,而不是Google云端硬盘。
dev.e.loper

@ dev.e.loper为您添加了有关此信息的一些信息。
Ampt

3

我建议在服务器上保留1个文档的永久副本。当客户端连接到服务器时,您会UPDATE向客户端发出所有更改的命令。

更新工作流程

用户导致触发更改->客户端发送UPDATE到服务器->服务器发送UPDATE到客户端

可行的触发器

  1. 用户点击保存
  2. 用户完成特定任务
    • 完成单元格的编辑
    • 完成编辑句子/段落/行
  3. 用户点击撤消
  4. 用户按回车键
  5. 用户键入一个密钥(保存每次更改)

更新实施

我建议能够使用一系列UPDATE命令来重新创建文档,以便服务器存储每个UPDATE,并且当新客户端连接时,可以向客户端发送一系列更新,并且它本身可以重新创建文档以显示给用户。同样,您也可以选择使用SAVE单独的命令,并将UPDATE更改为可用于UNDO请求的临时更改,并在服务器关闭或所有客户端断开连接的情况下,让SAVE实际存储该重新打开的命令。


2
解决冲突呢?如果两个人同时编辑同一文本区域怎么办?另外,这似乎给数据库增加了负担,这是OP希望避免的事情。不过,对于他的需求来说可能是可行的。
Ampt

@Ampt我使用此模型制作了一个电子表格,由于发生冲突,要更新的每个特定任务都完全替换为最新版本。因此,最后完成单元格编辑的人员将完全合并以前更新的单元格,而不会合并。
Korey Hinton

1
因此,如果这是一个单词文档,那么一个句子会覆盖另一个句子吗?
Ampt

@Ampt是的,或者,您可以实现一种锁定正在处理的内容的方法,但是我采取了简单的方法。
Korey Hinton

3

1)看一下Knockout.js

它遵循MVVM模式,并将根据对模型的更改自动向视图推送通知。例如,查看它们的可观察数组,以提供有关它们如何执行操作的更多信息。

2)将其与SignalR混合使用,您现在应该可以将通知发送给处理文档的其他用户。从他们的网站:

SignalR还提供了一个非常简单的高级API,用于在ASP.NET应用程序中执行服务器到客户端RPC(从服务器端.NET代码在客户端浏览器中调用JavaScript函数),并添加了用于连接管理的有用钩子,例如连接/断开事件,分组连接,授权。

因此,您需要在Knockout.js的模型级别上具有一些挂钩,以便在发生更改时进行一些SignalR调用。其他客户端将收到SignalR的通知,然后触发模型副本的相应更改,这将推回到其视图。

这是两个框架的有趣组合,您应该能够搜索和收集更多信息来处理细节。

例如,此代码项目示例专门解决Co Working UIs and Continuous Clients了您似乎正在尝试做的事情。

新时代的Web应用程序可能需要提供新时代的用户体验-并应正确处理共同工作和连续的客户场景。这涉及确保用户界面本身在设备之间和用户之间正确同步,以确保应用程序和用户界面的状态保持“原样”。

这篇博客文章似乎是一系列博客文章的切入点,讨论了这两个软件包的用法,并与传统的ASP.NET方法进行了对比。在设计网站时,可能会提供一些注意事项。

这篇博客文章似乎更加基础,并为组合这两个软件包提供了基础。

披露:我与上述任何链接都不隶属,也没有真正研究过它们的内容以了解声音的正确性或正确性。


2

解决方案是运营转型(OT)。如果您还没有听说过,那么OT是一类执行多站点实时并发的算法。OT就像实时git。它可以处理任何延迟(从零到延长假日)。它允许用户以低带宽进行实时并发编辑。OT使您最终在多个用户之间保持一致,而无需重试,没有错误并且没有任何数据被覆盖。

但是实施OT是一项艰巨的任务,而且非常耗时。因此,您可能要使用http://sharejs.org/之类的外部库。


1
Google Realtime API正在执行OT youtu.be/hv14PTbkIs0?t=14m20s 他们在客户端和服务器上都执行此操作。我无法通过阅读ShareJS文档得到明确的答案,但我假设ShareJS在客户端和服务器上都可以进行OT吗?
dev.e.loper

1

它主要取决于文档的类型以及用户的协作方式。

但是,我会:

  1. 让所有客户端每隔一段时间将未保存的更改发送到服务器(取决于用户使用文档的方式)。
  2. 服务器将增量存储在用户的会话中(即使对于胖客户端,您也需要类似会话的内容)
  3. 其他客户在编辑/查看同一文档时会得到这些临时更改,或者至少暗示可能会有这种更改。

优点:

  • 除非有人单击“保存”,否则没有数据库更新
  • 客户端崩溃的情况下的备份(会话期间)
  • 您的服务器决定如何以及将哪些数据转发给哪个客户端(例如,您可以仅通过注释即可启动该功能,然后实现更复杂的合并和突出显示)

缺点:

  • 并非“实时”-例如,您每30秒发送一次,但有人在那段时间内输入3个句子。
  • 更多网络流量-取决于您的文档和协作
  • 可能是大型会议
  • 如果许多用户合作并进行许多更改,则可能需要大量的计算工作

1

本质上,您要问的是如何处理共享的可变状态。储蓄是容易的部分;但是您如何处理多个人同时编辑同一事物?您希望所有用户都在实时同步同步编辑的同时查看同一文档。

您可能已经聚集了,这是一个难题!有一些实用的解决方案:

  1. 修改您的应用程序要求,以不允许进行真正的同时编辑。可以像源控制系统一样合并编辑内容,并将结果广播到每个客户端。您可以自己构建它,但这会带来较差的用户体验。
  2. 将状态突变的同步外包给与您现有技术集成的开源解决方案。ShareDB是该领域的当前领导者。它基于运营转型,并至少在一个生产系统中使用。这将解决您所关心的保存问题,但对于任何协作应用程序所必需的任何其他UX功能都无济于事。
  3. 使用诸如Convergence(免责声明:我是创始人)之类的现成平台为您处理所有困难的工作。您还将获得用于实时协作的其他工具,例如光标/鼠标跟踪,选择和聊天,以快速建立出色的协作体验。有关所有现有工具的全面概述,请参见此问题
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.