我正在研究类似于pastebin的东西(是的, 通用),但允许多个用户编辑。显而易见的问题是多个用户试图编辑同一个文件。当一个用户正在处理它时,我正在考虑锁定文件(这不是最好的解决方案,但我不需要太复杂的东西),但为了防止/警告用户我显然需要一个用于监控每个用户的编辑会话的系统。使用数据库和ajax,我正在考虑两种解决方案。
第一种方法是让编辑页面以任意间隔(例如一分钟)ping服务器,它将更新数据库中的编辑会话条目。然后,下一次脚本请求编辑时,它会检查最近的ping,如果最近一次是另一个任意时间,比如五分钟,那么我们假设前一个用户已退出,并且可以再次编辑该文件。当然,这种方法的问题在于前一个用户退出的假设只是一个假设。他可能会有一个片状的Wi-Fi连接,只是在窗户仍然打开的情况下辍学十分钟。
当然,为了处理这个问题,我们必须让服务器响应来自先前关闭的会话的新请求并发出错误,告诉客户端指出用户他的会话已经结束,然后通过将其保存为服务器上的另一个文件并要求用户手动合并等来处理它。不言而喻,对于最终用户来说这是相当可怕的。
所以我想到了另一个解决方案。当用户的会话结束时,也可能会触发unload
事件,但我无法确定这是否可靠。
有没有人对此问题有任何其他更优雅的解决方案?
答案 0 :(得分:6)
如果您希望文件的并发编辑次数较少,则可以在db中存储该文件的版本号,当用户将文件下载到浏览器中时,它们也会获得版本号。如果版本号匹配,则只允许他们上传更改。第一个上传胜利。检测到冲突时,您应该发回最新文件和用户的更改,以便用户可以手动合并更改。优点是,即使同一个用户同时进行两次编辑,这也可以工作。如果此功能最终被频繁使用,您可以添加类似于diff工具使用的客户端合并(但在这种情况下您可能需要保留旧版本)。
答案 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”一次,获取当前版本号 - 您已经知道他们正在编辑的版本,所以如果有新版本,您可以让他们知道并让他们下载最新版本进行改动。
这种方法的主要好处是用户永远不会锁定文件,因此您不需要任何“超时”。
答案 2 :(得分:0)
我会说你走在正确的轨道上。我可能会实现一个混合解决方案:
有一个名为“active_edits”的表或类似的表,其中包含document_id,user和last_update_time的列。让我们说你的ping时间是1分钟,你的超时是5分钟。所以用例看起来像这样:
鲍勃打开一份文件。它检查last_update_time。如果超过5分钟,请使用Bob和当前时间更新表。如果不是,则其他人正在处理该文档,因此请提供错误消息。假设它没有被编辑,Bob会在文档上工作一段时间,客户端会每分钟更新一次更新时间。我会说做包括“完成编辑”按钮和onunload处理程序。 Onunload,从我理解的可以是片状的,但也可以添加它。这两个都会向服务器发送一个只发送的帖子,说Bob完成了。即使Bob没有点击“完成编辑”并且没有点亮,最糟糕的情况是另一个用户需要等待5分钟才能进行编辑。优点是,如果这些正常工作(公平的假设),那么系统工作得更好。
如果您描述了Bob处于无线连接状况不佳或休息的情况:我会说这不是什么大问题。你的ping函数应该确保自Bob上次ping之后该文档还没有被其他人接管。如果有,只要给Bob一条消息说“其他人已经开始处理该文档”并给他们重新加载的选项。
编辑:此外,我会调查window.onbeforeunload,而不是onunload。我相信它早先执行。我相信这是功能网站(包括slashdot)用于确认您确实要离开页面。我认为它适用于主流浏览器,除了Opera。
答案 3 :(得分:0)
正如这个问题How do you manage concurrent access to forms?一样,我不会尝试实施悲观锁定。在无状态环境中可靠地工作是非常困难的。相反,我会使用乐观锁定。但是,在这种情况下,我使用类似文件的SHA哈希值来确定自用户上次从文件读取以来文件是否已更改。对于每个更改文件的请求,您将运行文件字节的SHA哈希值,并将其与您第一次读取数据时提取的版本进行比较。如果已更改,则拒绝更改并强制用户再次进行编辑(提取文件内容的新副本)或提供更高级别的冲突解决方案。