监控用户会话以防止编辑冲突。

5
我正在开发类似于pastebin的东西(是的,它很通用),但允许多个用户进行编辑。显而易见的问题是多个用户试图编辑同一文件。我考虑锁定文件,当一个用户在编辑时(这不是最好的解决方案,但我不需要太复杂的东西),但为了防止/警告用户,我显然需要一个监视每个用户编辑会话的系统。使用数据库和ajax,我考虑了两个解决方案。
第一个解决方案是使编辑页面在任意时间间隔(例如一分钟)向服务器发送ping请求,并更新数据库中的编辑会话条目。然后,在下一次脚本请求编辑时,它会检查最近的ping,如果最近的ping是另一个任意时间之前(例如五分钟),那么我们假设上一个用户已经退出并且文件可以再次编辑。当然,这种方法的问题在于假设上一个用户已经退出只是一种假设。他可能有不稳定的Wi-Fi连接,窗口仍然打开,而实际上只是掉线了十分钟。
当然,要解决这个问题,我们必须让服务器对来自先前关闭会话的新请求进行响应,并返回错误,告诉客户端指出用户的会话已结束,然后通过将其保存为服务器上的另一个文件并要求用户手动合并等方式来处理它。毫无疑问,这对最终用户来说非常糟糕。
所以我想到了另一个解决方案。也许可以在用户会话结束时触发unload事件,但我不能确定这是否可靠。
有没有其他更优雅的解决方案?
4个回答

6
如果您预计文件的并发编辑数量较少,可以在数据库中存储文件的版本号,在用户将文件下载到其浏览器时,他们也会得到版本号。只有当版本号匹配时,才允许上传更改。先上传者获胜。当检测到冲突时,应返回最新的文件和用户的更改,以便用户可以手动合并更改。优点是即使是同一用户进行两个同时编辑,这也可以正常工作。如果该功能经常使用,则可以添加类似于差异工具使用的客户端合并(但在这种情况下,您可能需要保留旧的修订)。

2
你最好选择“合并”方案。使用这种方法,只需要在用户将其文档发布到服务器时检查更改即可。
基本的步骤是: 1. 用户A获取编辑文档,文档版本为1 2. 用户B获取编辑文档,文档版本为1 3. 用户B发布一些更改,包括基础版本号为1 4. 服务器更新文档,文档现在版本为2 5. 用户B发布一些更改,包括基础版本号为1 6. 服务器响应说文档自用户开始编辑以来已经发生了更改,并向用户发送新文档和他们的版本 - 用户随后需要将任何更改合并到文档版本2中,并返回到服务器。用户实际上正在编辑文档版本2 7. 用户A发布一些更改,包括版本号2 8. 服务器更新文档,现在版本为3
您仍然可以每分钟执行一次“ping”,以获取当前版本号 - 您已经知道他们正在编辑哪个版本,因此如果有新版本可用,您可以让他们知道并让他们下载最新版本进行更改。
这种方法的主要优点是用户不会锁定文件,因此您不需要任何任意的“超时”。

这是一个很好的答案,但不是我正在寻找的:协作编辑部分对于共享部分来说真的很小,如果我没有表达清楚,很抱歉。采用这种解决方案会使事情变得更加复杂 - 对于一个简单的文本/代码共享应用程序来说太复杂了。考虑到用户交互的复杂性,我需要考虑的边缘情况数量是相当不可能的。尽管如此,这是一个很好的答案,并且在等待下一个答案的时候给了我一些思考的东西... - Yi Jiang

0

我认为你走在了正确的道路上。我可能会实现一个混合解决方案:

有一个名为“active_edits”或类似名称的单个表,其中包含文档ID、用户和最后更新时间的列。假设您的ping时间为1分钟,超时时间为5分钟。因此,使用情况如下:

Bob打开一个文档。它检查最后更新时间。如果超过5分钟,则使用Bob和当前时间更新表。如果没有,则其他人正在编辑该文档,因此会出现错误消息。假设它没有被编辑,Bob会在文档上工作一段时间,并且客户端每分钟ping一次更新时间。

我建议包括“完成编辑”按钮和onunload处理程序。根据我的理解,onunload可能会出现问题,但最好还是添加它。这两者都将向服务器发送一个仅发送的帖子,说明Bob已经完成。即使Bob没有点击“完成编辑”并且onunload出现故障,最坏的情况也是另一个用户必须等待5分钟才能进行编辑。优点是,如果这些通常有效(公平的假设),则系统的工作效果会更好。

在你所描述的情况下,如果Bob处于不良无线连接或休息状态:我认为这并不是什么大问题。您的ping函数应确保自Bob上次ping以来文档尚未被其他人接管。如果是这样,请给Bob一个消息,说“有人已经开始在文档上工作”,并给他们重新加载的选项。
编辑:此外,我将研究window.onbeforeunload,而不是onunload。我相信它会更早执行。我相信这是网站(包括slashdot)用来允许您确认您是否真的要离开页面的功能。我认为它适用于主要浏览器,除了Opera。

0
与这个SO问题如何管理表单的并发访问?一样,我不会尝试实现悲观锁定。在无状态环境中,要使其可靠工作太困难了。相反,我会使用乐观锁定。但是,在这种情况下,我使用了类似于文件的SHA哈希值来确定自用户上次从文件中读取以来文件是否已更改。对于每个更改文件的请求,您将运行文件字节的SHA哈希值,并将其与首次读取数据时提取的版本进行比较。如果已更改,则拒绝更改,并强制用户重新编辑(拉取文件内容的新副本),或者提供更高级的冲突解决方案。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接