【问题标题】:Monitoring User Sessions to Prevent Editing Conflict监控用户会话以防止编辑冲突
【发布时间】:2010-08-20 10:51:05
【问题描述】:

我正在研究类似于 pastebin 的东西(是的,它是 通用的),但允许多用户编辑。明显的问题是多个用户试图编辑同一个文件。我正在考虑当一个用户正在处理文件时锁定文件(这不是最好的解决方案,但我不需要任何太复杂的东西),但为了防止/警告用户,我显然需要一个用于监控每个用户的编辑会话的系统。使用数据库和 ajax,我正在考虑两种解决方案。

第一种方法是让编辑页面以任意间隔(例如一分钟)对服务器执行 ping 操作,它会更新数据库中的编辑会话条目。然后下次脚本请求编辑时,它会检查最近的 ping,如果最近的 ping 是另一个任意时间之前,比如五分钟,那么我们假设之前的用户已经停止,并且可以再次编辑文件。当然,这种方法的问题在于,前一个用户已经退出的假设只是一个假设。他可能是因为 wi-fi 连接不稳定,只是在 10 分钟内掉线,一直开着窗户。

当然,为了处理这个问题,我们必须让服务器响应来自先前关闭会话的新请求并报错,告诉客户端向用户指出他的会话已经结束,然后通过例如将其另存为服务器上的另一个文件并要求用户手动合并它等来处理它。不用说,这对最终用户来说是相当可怕的。

所以我开始考虑另一种解决方案。当用户会话结束时,也有可能触发unload 事件,但我不确定这是否会可靠地工作。

对于这个问题,还有其他更优雅的解决方案吗?

【问题讨论】:

    标签: javascript ajax session conflict


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

      您最好选择“合并”解决方案。使用这种方法,您只需在用户将文档发布到服务器时检查更改。

      基本方法是: 1.用户A获取文档进行编辑,文档为版本1 2. 用户 B 获取要编辑的文档,文档为版本 1 3. 用户 B 发布了一些更改,包括基础版本号 1 4.服务器更新文档,现在文档在版本2 5. 用户 B 发布了一些更改,包括基础版本号 1 6. 服务器响应说自从用户开始编辑后文档已更改,并将新文档及其版本发送给用户 - 然后用户需要将他们的更改合并到文档版本 2 中,然后发回服务器。用户现在基本上正在编辑文档版本 2 7.用户A发布了一些更改,包括2的版本号 8. 服务器更新文档,现在是第3版

      您仍然可以每分钟执行一次“ping”以获取当前版本号 - 您已经知道他们正在编辑的版本,因此如果有新版本可用,您可以让他们知道并让他们下载最新版本将其更改为。

      这种方法的主要好处是用户永远不会锁定文件,因此您不需要任何任意的“超时”。

      【讨论】:

      • 这是一个很好的答案,但它真的不是我想要的:协作编辑部分对于共享部分来说真的是次要的,如果我没有说清楚,对不起。采用这种解决方案会使事情变得更加更加复杂——对于简单的文本/代码共享应用程序来说太复杂了。考虑到这里用户交互的复杂性,我需要考虑的边缘案例的数量将是……完全不可能的。不过,很好的答案,在我等待下一个答案时给了我一些思考......
      【解决方案3】:

      我会说你在正确的轨道上。我可能会实施一个混合解决方案:

      有一个名为“active_edits”的表或类似的表,其中包含 document_id、用户和 last_update_time 列。假设您的 ping 时间为 1 分钟,超时时间为 5 分钟。所以一个用例看起来像这样:

      Bob 打开一个文档。它检查 last_update_time。如果超过 5 分钟,则用 Bob 和当前时间更新表。如果不是,则其他人正在处理该文档,因此请给出错误消息。假设它没有被编辑,Bob 在文档上工作了一段时间,客户端每分钟 ping 一个更新时间。

      我会说 包括一个“完成编辑”按钮和一个 onunload 处理程序。 Onunload,据我了解 可能 不稳定,但不妨添加它。这两个都会向服务器发送一个只发送的帖子,说 Bob 完成了。即使 Bob 没有点击“完成编辑”并且 onunload 失败,最坏的情况是另一个用户必须再等待 5 分钟才能进行编辑。好处是,如果这些正常工作(一个公平的假设),那么系统工作得更好一些。

      如果您描述了 Bob 无线连接不良或休息的情况:我想说这没什么大不了的。您的 ping 功能应确保自 Bob 上次 ping 以来该文档没有被其他人接管。如果有,只需给 Bob 一条消息,说“其他人已开始处理该文档”,并让他们选择重新加载。

      编辑:另外,我会调查window.onbeforeunload,而不是 onunload。我相信它执行得更早。我相信这是网站(包括斜线点)用来让您确认您确实想要离开页面的功能。我认为它适用于除 Opera 之外的主要浏览器。

      【讨论】:

        【解决方案4】:

        对于这个 SO 问题How do you manage concurrent access to forms?,我不会尝试实现悲观锁定。在无状态的环境中可靠地工作太难了。相反,我会使用乐观锁定。但是,在这种情况下,我使用文件的 SHA 哈希值来确定自用户上次读取文件以来文件是否已更改。对于更改文件的每个请求,您将运行文件字节的 SHA 哈希,并将其与您在第一次读取数据时提取的版本进行比较。如果已更改,则拒绝更改并强制用户再次进行编辑(提取文件内容的新副本)或提供更出色的冲突解决方案。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-05-18
          • 1970-01-01
          • 2019-03-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-06-21
          • 2014-08-14
          相关资源
          最近更新 更多