【问题标题】:What can I do to prevent write-write conflicts on a wiki-style website?我能做些什么来防止 wiki 风格网站上的写-写冲突?
【发布时间】:2011-10-29 15:53:00
【问题描述】:

在 wiki 风格的网站上,我可以做些什么来防止或减轻write-write conflicts,同时仍然允许网站快速运行并保持网站易于使用?

我预见的问题是这样的:

  1. 用户 A 开始编辑文件
  2. 用户 B 开始编辑文件
  3. 用户 A 完成文件编辑
  4. 用户 B 完成文件编辑,意外覆盖了用户 A 的所有编辑

以下是我想出的一些方法:

  • 拥有某种签出/签入/锁定系统(尽管我不知道如何防止人们将文件签出“太长时间”,而且我不希望用户因未被允许进行编辑)
  • 拥有某种diff 系统,显示用户提交更改并允许某种合并时所做的其他更改(但我担心这将难以创建并且会使网站“太难”使用)
  • 通知用户并发编辑他们正在进行更改(某种 AJAX?)

还有其他方法可以解决这个问题吗?有没有很好地实现这一点的网站示例?

【问题讨论】:

    标签: usability wiki


    【解决方案1】:

    记住上次更改的版本号(或 ID)。然后在写之前阅读条目并比较这个版本是否仍然相同。

    如果发生冲突,请通知尝试写入同时更改的条目的用户。用差异支持他。

    大多数 wiki 都是这样做的。 MediaWiki, Usemod, etc.

    【讨论】:

    • 如果关注的是性能,可能值得一提的是,使用缓存(即使用 memcached)可以避免需要访问数据库来检索页面的最后修改日期。
    • 如果“一次”发生超过 1 次保存,这将产生竞争条件。
    • @Andy:好点。将其更改为版本号。也可以是一些 ID。
    • 那叫CAS
    【解决方案2】:

    三向合并:首先要指出的是,大多数并发编辑,尤其是在较长的文档上,都是针对文本的不同部分进行的。因此,通过注意用户 A 和 B 获得了哪个修订版,我们可以进行三向合并,如 Bill Ritcher of Guiffy Software 所述。三向合并可以识别从原始文章中进行编辑的位置,除非它们发生冲突,否则它可以默默地将两个编辑合并到新文章中。理想情况下,此时执行合并并向用户 B 显示新文档,以便她可以选择进一步修改它。

    碰撞分辨率: 当两个编辑器都编辑了同一部分时,这会给您留下场景。在这种情况下,合并其他所有内容并将三个版本的文本提供给用户 B - 即包括原始文本 - 文本框中包含用户 A 的版本或用户 B 的版本。该选择取决于您是否认为默认应该是接受最新的(用户只需单击保存以保留他们的版本)或强制编辑器编辑两次以获取他们的更改(他们必须将更改重新应用到编辑器 A该部分的版本)。

    使用像这样的三向合并可以避免锁定,这在网络上很难很好地处理(你让他们锁定多长时间?),以及加重“你可能想再看一遍”的情况,仅适用于论坛式回复。它还保留了 web 的 post-response 风格。

    如果您想对其进行 Ajax 处理,请在用户 A 的版本编辑时将用户 A 的版本动态 3 路合并到用户 B 的版本中,并通知他们。现在这将是令人印象深刻的。

    【讨论】:

      【解决方案3】:

      在 Mediawiki 中,服务器接受第一个更改,然后在保存第二个编辑时出现冲突页面,然后第二个人将两个更改合并在一起。见Wikipedia: Help:Edit Conflicts

      【讨论】:

        【解决方案4】:

        使用锁定机制可能是最容易实现的。每篇文章都可以有一个与之关联的锁定字段和一个锁定时间。如果锁定时间超过某个设定值,您会认为锁定无效并在查看文章进行编辑时将其删除。您还可以跟踪打开的锁并在会话关闭时将其删除。您还需要在数据库中实现一些并发控制(可能是自动生成的时间戳),以便您可以确保您正在签入对您签出的版本的更新,以防两个人能够编辑同时发表文章。只有版本正确的人才能成功签入编辑。

        您也许还可以找到一个差异引擎来构建差异,尽管在 wiki 编辑器中显示它们可能会出现问题——实际上显示差异可能比构建差异更难。您将依赖版本控制系统来检测您何时需要拒绝编辑并执行差异。

        【讨论】:

        • WikiDot 的锁定时间为 15 分钟空闲时间。一旦你写了一些东西,时间就会重置为 15 分钟。
        【解决方案5】:

        在 Gmail 中,如果我们正在对邮件进行回复,而其他人在我们仍在键入时发送了回复,则会出现一个弹出窗口,指示有新的更新,并且更新本身会显示为另一个帖子,而无需重新加载页面.这种方法将满足您的需求,如果您可以使用 Ajax 显示确切的帖子,其中包含指向刚刚更新内容的差异的链接,而用户 B 仍在忙于输入他的条目,那就太好了。

        【讨论】:

        • 不错。我想在维基百科上看到这个。
        【解决方案6】:

        正如 Ravi(和其他人)所说,您可以使用 AJAX 方法并在另一项更改正在进行时通知用户。提交编辑后,只需指出文本差异,让第二个用户弄清楚如何合并两个版本。

        不过,除此之外,我还想补充一些您可以尝试的新内容:在编辑进行编辑时打开他们之间的聊天对话框。例如,您可以为此使用嵌入式Gabbly 之类的东西。


        我说,最好的冲突解决方案是直接对话。

        【讨论】:

          【解决方案7】:

          您的问题(丢失更新)最好使用Optimistic Concurrency Control 解决。

          一种实现是在系统的每个可编辑实体中添加一个version列。在用户编辑时,您加载行并在用户身上显示 html 表单。一个隐藏字段给出了版本,比如说 3。更新查询需要类似于:

          update articles set ..., version=4 where id=14 and version=3;
          

          如果返回的行数为 0,则说明第 14 条已经有人更新了。那么你需要做的就是如何处理这种情况。一些常见的解决方案:

          1. 最后一次提交获胜
          2. 第一次提交获胜
          3. 合并有冲突的更新
          4. 让用户决定

          您可以使用 timestamp 而不是递增的 version int/long,但不建议这样做,因为:

          在集群环境中从 JVM 检索当前时间并不一定安全,因为在集群环境中节点可能没有时间同步。

          (引用Java Persistence with Hibernate

          更多信息请访问hibernate documentation

          【讨论】:

            【解决方案8】:

            在我的办公室,我们的政策是所有数据表都包含 4 个字段:

            • 创建者
            • 创建日期
            • 上次更新者
            • 上次更新日期

            这样就可以很好地跟踪记录谁对记录做了什么,至少最近一次。

            但最重要的是,将屏幕上当前或已编辑记录的 LastUpdateDate 与数据库中的值进行比较变得非常容易(需要您将其存储在页面上、cookie 中等等)与数据库中的值。如果值不匹配,你可以从那里决定做什么。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2010-10-20
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2010-12-06
              • 2010-12-06
              • 2021-09-11
              • 2011-10-25
              相关资源
              最近更新 更多