当多个用户正在查看一条记录并且有1人更新该记录时,如何通知其他人该记录已更新?

Posted

技术标签:

【中文标题】当多个用户正在查看一条记录并且有1人更新该记录时,如何通知其他人该记录已更新?【英文标题】:When multiple users are viewing a record and 1 person updates the record, how to notify other the record is updated? 【发布时间】:2016-03-24 15:43:25 【问题描述】:

在我的项目管理应用程序中,我想解决多个用户查看同一任务记录并且其中一个或多个用户更新某些任务数据而其他人正在查看它的问题。


这是一个场景……

用户#1查看任务#1用户#2查看任务#1

现在用户#2更新任务#1描述

用户 #1 现在正在查看任务记录,但他的视图显示了不同的过时 描述,因为 用户 #2 刚刚更新它!更糟糕的是,他可能想自己编辑描述,这将完全覆盖用户 #2 的描述更新。


这是问题的 1 个示例。只需添加更多用户,问题就会成倍增加!

理想情况下,我会使用 Sockets 之类的东西或 Pusher.com 之类的服务来更新所有用户的数据,只要有任何用户进行了更新。然而,这个项目将在数百台服务器上运行,并且就服务器要求而言功能有限,因此套接字甚至像 Pusher 这样的服务都是不可能的!

解决方案的另一个想法是基于 Twitter 所做的。如果您查看某人的 Twitter 页面,并且他们在您加载页面时发布了新帖子。它将显示一条通知消息 DIV,告诉您有 X 条新帖子,并为您提供一个链接,让您单击以重新加载带有最新帖子的帖子流。

我相信类似的方法可以适用于我的项目。如果用户在其他用户查看该任务记录时对任何任务数据进行更新。它会在任务模式窗口上显示一条通知消息,告诉用户任务数据已更新,他们应该重新加载任务。

为了完成这项工作,我知道需要每隔一段时间发出一些 AJAX 请求。

然后,该 AJAX 请求需要比较对任务记录进行的最后更新的时间戳,并将其与查看任务记录的用户开始查看它的时间或自他们上次重新加载任务以来的时间进行比较。

我觉得我的逻辑缺少一块拼图?这是正确的还是我遗漏了什么?

谁能解释一下我该怎么做或告诉我我的想法是否正确?

我知道简而言之,我只需要确定任务最后修改的时间戳是否是在其他用户开始查看任务之后。在某些时候,虽然我觉得用户时间也应该更新?

更新

我完全忘记了 Stack Overflow 对问题和答案的确切任务!当您查看 SO 上的页面并更新答案时,它将显示一条通知消息,告诉您重新加载答案并提供重新加载答案的链接。这就是我想做的!

*** 使用 Web Sockets 来做到这一点,但在我的应用程序中,它是一个用于许多不同服务器配置的插件,我不能使用 Sockets。我正在尝试使用 AJAX 实现类似的结果。即使它是每 30 秒发出一次 AJAX 请求以获取任务修改时间并将其与另一个进行比较以确定用户是否应该重新加载任务数据在我的情况下也可以工作

【问题讨论】:

您可以从dev-metal.com/architecture-*** 开始,尤其是更新#3 和highscalability.com/stack-overflow-architecture 和meta.stackexchange.com/questions/10369/… 是我找到的一些相关链接。还有更多,但这应该可以帮助您入门。我希望这会有所帮助。 @Fred-ii- 谢谢,据我所知,他们在这里使用 Web 套接字来做这件事,这是有道理的,但在我的情况下,最好的路线是对将使用我的应用程序的用户做的受到限制并且不能使用套接字,所以我认为我应该能够使用 AJAX 轮询技术实现相同的结果 不客气,杰森。我和你的想法一样。但是,我在该领域还不够精通,无法进一步发表评论(我知道一些,但不像 Stack 上的其他成员那样),但他们也可能同时使用这两种方法。您可能只需使用 AJAX 轮询技术就可以侥幸逃脱。 @Fred-ii- 在这里相同。我知道 5 到 6 年前,AJAX 方法被到处使用,因为它是我们当时所拥有的!所以我知道这是可能的。它有缺点,但就我而言,这是我最好的选择,因为我的应用程序是一个插件,可以安装在许多服务器配置上。它在 SugarCRM 内部,因此至少对于企业中将使用它的大多数用户来说,它是私人流量,所以即使是每 15-30 秒发出的 AJAX 请求来比较 2 个时间戳,我相信也能起到作用。如果是我的选择,我会使用 Pusher.com 并在 5 分钟内完成!不过希望其他人也能加入这里=) @JasonDavis 您最终使用了基本的 AJAX 轮询技术吗? 【参考方案1】:

这个概念和想法相当琐碎,实施起来应该不会有任何困难。如您所说,您需要为每个任务提供 Last Updated 时间戳,如果您采用所描述的方法,还需要客户端上的 Last Update 时间戳。通常,当用户正在查看任务时,您会希望(在客户端,javascript):

    向服务器查询正在使用 AJAX 查看的 TaskLast Updated 时间戳。 如果正在查看的 TaskLast Updated 时间戳大于(更新)客户端上的 Last Update 时间戳,请转到步骤 5 . 等待(异步)n 秒。 转到第 1 步。 通知用户正在查看的任务已更新。 结束(由于客户端已经知道Task已更新,因此无需继续轮询是否已更新)。

一种方法可以简单地使用setInterval() 创建一个异步间隔,一旦确定发生更新,该间隔就会被清除,之后会向用户显示一条消息。

var lastUpdate = Date.now();
var intervalDuration = 30000; // 30 seconds
var interval = setInterval(function () 
    var xhr = new XMLHttpRequest();
    ...
    xhr.onload = function () 
        if (...)  // if the Task's Last Updated timestamp is newer than lastUpdate
            clearInterval(interval);
            // show message to user that the Task has been updated
        
    ;
, intervalDuration);

我可以想象,在一个非常庞大的系统中,这种方法很容易不够用,但对于非企业级解决方案或后续 UI 改进,这可能是一种快速、廉价且引人注目的解决方案。

当然,还有可能更强大、更灵活的替代方案:long-polling or websockets。

【讨论】:

【参考方案2】:

您的问题过于宽泛,但您基本上是在描述 Pub/Sub。

想法

每当用户进入您的网站时,他都会获得一个令牌来识别他们。

如果他访问一个任务,他会订阅该任务,这意味着对它的任何修改都会提醒他。

他轮询服务器以检查是否有任何警报给他。

实施

关于实施,您可以为每个用户的订阅设置一个列表。 使用您的示例:

User1 订阅 (Task1, Task2)

User2 订阅 (Task1)

对于每个订阅,您都会保留一些值,代表用户对该主题的最后状态(例如,最后修改时间戳)。

用户每 n 秒轮询一次您的应用程序。每当请求到达您的应用程序时,您就会检查用户的订阅,并检查时间戳是否已更改(如果他们有最新的)。如果是这样,您更新用户拥有的最后一个状态,并为他检索已更改任务的新值。

需要考虑的事项

此订阅列表将不断被访问,因此请注意将其存储在何处。如果在内存中,请考虑您需要在不同的实例之间共享它(如果您是负载平衡)。你可以使用 Redis,或者类似的东西。

您无需在每次需要检索数据时都访问数据库。如果有人订阅它,请将其保存在缓存中。

【讨论】:

以上是关于当多个用户正在查看一条记录并且有1人更新该记录时,如何通知其他人该记录已更新?的主要内容,如果未能解决你的问题,请参考以下文章

当C中有多个同名记录时如何删除记录

我如何更新数据库中的通话记录数据(java android)

mysql存储引擎

oracle中记录被另一个用户锁住的原因与解决办法

选择更新锁定

MySQL 在哪里 ()