如何防止 wiki 风格网站上的写入冲突?
在 wiki 风格的网站上,我可以采取哪些措施来防止或减轻写入冲突同时仍然允许网站快速运行并保持网站易于使用?
我预见的问题是这样的:
- 用户 A 开始编辑文件
- 用户 B 开始编辑文件
- 用户 A 完成编辑文件
- 用户 B 完成编辑文件,意外覆盖了用户 A 的所有编辑
以下是我想出的一些方法
- :某种签出/签入/锁定系统(尽管我不知道如何防止人们将文件签出“太长时间”,并且我不希望用户因不被签出而感到沮丧允许进行编辑)
- 有某种显示其他更改的diff系统当用户提交更改并允许某种合并时进行(但我担心这将很难创建并且会使网站“太难”而无法使用)
- 通知用户并发编辑而正在做出改变(某种 AJAX?)
还有其他方法可以解决这个问题吗? 有哪些网站可以很好地实现这一点的例子吗?
On a wiki-style website, what can I do to prevent or mitigate write-write conflicts while still allowing the site to run quickly and keeping the site easy to use?
The problem I foresee is this:
- User A begins editing a file
- User B begins editing the file
- User A finishes editing the file
- User B finishes editing the file, accidentally overwriting all of User A's edits
Here were some approaches I came up with:
- Have some sort of check-out / check-in / locking system (although I don't know how to prevent people from keeping a file checked out "too long", and I don't want users to be frustrated by not being allowed to make an edit)
- Have some sort of diff system that shows an other changes made when a user commits their changes and allows some sort of merge (but I'm worried this will hard to create and would make the site "too hard" to use)
- Notify users of concurrent edits while they are making their changes (some sort of AJAX?)
Any other ways to go at this? Any examples of sites that implement this well?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
记住最后一次更改的版本号(或 ID)。 然后在写入之前阅读该条目并比较该版本是否仍然相同。
如果发生冲突,请通知正在尝试写入同时已更改的条目的用户。 支持他的差异。
大多数维基百科都是这样做的。 MediaWiki,Usemod、等。
Remember the version number (or ID) of the last change. Then read the entry before writing it and compare if this version is still the same.
In case of a conflict inform the user who was trying to write the entry which was changed in the meantime. Support him with a diff.
Most wikis do it this way. MediaWiki, Usemod, etc.
三向合并:首先要指出的是,大多数并发编辑(尤其是较长文档)都是针对文本的不同部分。 因此,通过记录用户 A 和 B 获得的修订版本,我们可以进行三向合并,如 Guiffy Software 的 Bill Ritcher。 三向合并可以识别对原始文章的编辑位置,除非它们发生冲突,否则它可以默默地将两个编辑合并到新文章中。 理想情况下,此时执行合并并向用户 B 展示新文档,以便她可以选择进一步修改。
碰撞解决:
这会让您遇到两个编辑都编辑了同一部分的情况。 在这种情况下,合并其他所有内容并将三个版本的文本提供给用户 B(即,包括原始版本),其中文本框中包含用户 A 的版本或用户 B 的版本。 该选择取决于您是否认为默认应该接受最新版本(用户只需单击“保存”即可保留其版本)或强制编辑器编辑两次以获取更改(他们必须将更改重新应用到编辑器 A 的版本)该部分的版本)。
使用这样的三向合并可以避免锁定,这在网络上很难很好地处理(你让他们锁定多长时间?),以及令人烦恼的“你可能想再看一遍”的情况,这只会非常适合论坛风格的回复。 它还保留了网络的后响应风格。
如果您想稍微使用 Ajax,请在用户 A 的版本编辑时动态地将用户 A 的版本合并到用户 B 的版本中,并通知他们。 现在这将是令人印象深刻的。
Three-way merging: The first thing to point out is that most concurrent edits, particularly on longer documents, are to different sections of the text. As a result, by noting which revision Users A and B acquired, we can do a three-way merge, as detailed by Bill Ritcher of Guiffy Software. A three-way merge can identify where the edits have been made from the original, and unless they clash it can silently merge both edits into a new article. Ideally, at this point carry out the merge and show User B the new document so that she can choose to further revise it.
Collision resolution:
This leaves you with the scenario when both editors have edited the same section. In this case, merge everything else and offer the text of the three versions to User B - that is, include the original - with either User A's version in the textbox or User B's. That choice depends on whether you think the default should be to accept the latest (the user just clicks Save to retain their version) or force the editor to edit twice to get their changes in (they have to re-apply their changes to editor A's version of the section).
Using three-way merging like this avoids lock-outs, which are very difficult to handle well on the web (how long do you let them have the lock?), and the aggravating 'you might want to look again' scenario, which only works well for forum-style responses. It also retains the post-respond style of the web.
If you want to Ajax it up a bit, dynamically 3-way merge User A's version into User B's version while they are editing it, and notify them. Now that would be impressive.
在 Mediawiki 中,服务器接受第一个更改,然后当保存第二个编辑时,会出现一个冲突页面,然后第二个人将两个更改合并在一起。 请参阅维基百科:帮助:编辑冲突
In Mediawiki, the server accepts the first change, and then when the second edit is saved a conflicts page comes up, and then the second person merges the two changes together. See Wikipedia: Help:Edit Conflicts
使用锁定机制可能是最容易实现的。 每篇文章都可以有一个与其关联的锁定字段和锁定时间。 如果锁定时间超过某个设定值,您会认为锁定无效,并在签出文章进行编辑时将其删除。 您还可以跟踪打开的锁并在会话关闭时将其删除。 您还需要在数据库中实现一些并发控制(也许是自动生成的时间戳),以便您可以确保您正在签入对您签出的版本的更新,以防万一两个人能够编辑文章同时。 只有拥有正确版本的人才能成功签入编辑。
您也许还能够找到一个差异引擎,您可以用它来构建差异,尽管在 wiki 编辑器中显示它们可能会出现问题 - 实际上显示差异可能比构建差异更困难。 您将依靠版本控制系统来检测何时需要拒绝编辑并执行差异。
Using a locking mechanism will probably be the easiest to implement. Each article could have a lock field associated with it and a lock time. If the lock time exceeded some set value you'd consider the lock to be invalid and remove it when checking out the article for edit. You could also keep track of open locks and remove them on session close. You'd also need to implement some concurrency control in the database (autogenerated timestamps, perhaps) so that you could make sure that you are checking in an update to the version that you checked out, just in case two people were able to edit the article at the same time. Only the one with the correct version would be able successfully check in an edit.
You might also be able to find a difference engine that you could just use to construct differences, though displaying them in a wiki editor may be problematic -- actually displaying the differences is probably harder than constructing the diff. You'd rely on the versioning system to detect when you needed to reject an edit and perform a diff.
在 Gmail 中,如果我们正在回复邮件,而我们仍在键入邮件时其他人发送了回复,则会出现一个弹出窗口,指示有新的更新,并且更新本身会显示为另一篇帖子,而无需重新加载页面。 这种方法将满足您的需求,如果您可以使用 Ajax 显示确切的帖子,并提供刚刚更新内容的差异链接,而用户 B 仍在忙于输入他的条目,那就太好了。
In Gmail, if we are writing a reply to a mail and someone else sends a reply while we are still typing it, a popup appears indicating that there is a new update and the update itself appears as another post without a page reload. This approach would suit your needs and if you can use Ajax to show the exact post with a link to diff of what was just updated while User B is still busy typing his entry that would be great.
正如 Ravi(和其他人)所说,您可以使用 AJAX 方法并在另一项更改正在进行时通知用户。 提交编辑后,只需指出文本差异,然后让第二个用户弄清楚如何合并两个版本。
不过,我想添加一些您可以尝试的新功能:在编辑人员进行编辑时打开他们之间的聊天对话框。 例如,您可以使用嵌入式 Gabbly 之类的东西。
我说,最好的冲突解决方法是直接对话。
As Ravi (and others) have said, you could use an AJAX approach and inform the user when another change is in progress. When an edit is submitted, just indicate the textual differences and let the second user work out how to merge the two versions.
However, I'd like to add on with something new you could try in addition to that: Open a chat dialog between the editors while they're doing their edits. You could use something like embedded Gabbly for that, for instance.
The best conflict resolution is direct dialog, I say.
使用乐观并发控制可以最好地解决您的问题(丢失更新)。
一种实现是在系统的每个可编辑实体中添加一个版本列。 在用户编辑时,您加载该行并向用户显示 html 表单。 隐藏字段提供版本,假设3。 更新查询需要类似于:
如果返回的行数为 0,那么有人已经更新了第 14 篇文章。那么您需要做的就是如何处理这种情况。 一些常见的解决方案:
您可以使用 时间戳 ,而不是递增的 version int/long,但不建议这样做,因为:
(引自 Java Persistence with Hibernate)
更多信息请参见 休眠文档。
Your problem (lost update) is solved best using Optimistic Concurrency Control.
One implementation is to add a version column in each editable entity of the system. On user edit you load the row and display the html form on the user. A hidden field gives the version, let's say 3. The update query needs to look something like:
If rows returned is 0 then someone has already updated article 14. All you need to do then is how to deal with the situation. Some common solutions:
Instead of an incrementing version int/long you can use a timestamp but it's not suggested because:
(quote from Java Persistence with Hibernate)
Some more info at the hibernate documentation.
在我的办公室,我们有一个政策,所有数据表都包含 4 个字段:
这样就可以很好地审计跟踪谁对记录做了什么(至少最近是这样)。
但最重要的是,将屏幕上当前或已编辑记录的 LastUpdateDate 进行比较变得非常容易(要求您将其存储在页面上、cookie 中等)与数据库中的值。如果值不匹配,您可以从那里决定要做什么。
At my office, we have a policy that all data tables contain 4 fields:
That way there is a nice audit trail on who has done what to the records, at least most recently.
But most importantly, it becomes easy enough to compare the LastUpdateDate of the current or edited record on the screen (requires you to store it on the page, in a cookie, whatever, with the value in the database. If the values don't match, you can decide what to do from there.