建立类似于Stackoverflow的“收件箱”功能的推荐方法是什么?

时间:2012-03-12 04:41:20

标签: sql-server asp.net-mvc nhibernate caching inbox

我有一个asp.net-mvc网站,人们管理一个项目列表。根据一些算法,我可以判断一个项目是否已过时。当用户登录时,我希望它显示过时项目的数量(类似于我在收件箱中看到许多更新时)。

计算陈旧项目的算法有点慢,所以如果每次用户登录,我都必须:

  1. 为所有项目的所有项目运行查询
  2. 运行IsStale()算法
  3. 显示IsStale = true的计数
  4. 我的猜测是真的很慢。此外,在所有项目写入,我将不得不重新计算上面的内容,看看是否更改。

    我的另一个想法是创建一个表并在几分钟内运行一个工作来计算陈旧项目并将最新计数存储在此度量表中。然后只是在用户登录时查询。问题是我仍然要保持该表同步,如果它每分钟仅重新计算一次,如果人们更新项目,它将不会在一分钟后更改值。

    有任何想法以快速,可扩展的方式支持此收件箱概念,以提醒用户要审核的项目数量?

5 个答案:

答案 0 :(得分:10)

第一步始终是正确的需求分析。我们假设我是项目经理。我登录系统,它将我唯一的项目显示为 on time 。一位开发人员来到我的办公室告诉我他的活动有延迟。我选择开发人员的活动并更改其持续时间。系统仍然按时显示我的项目,所以我很乐意离开工作。

如果我在凌晨3点接到客户打来的电话询问我项目不再按时的原因,我怎么想?显然,非常惊讶,因为系统没有以任何方式警告我。为什么会这样?因为我必须等待30秒(为什么不是1秒?)下次运行预定作业才能更新项目状态。

这不是一个解决方案。必须立即向用户发送警告,即使运行IsStale()进程需要30秒。向用户显示loading...图像或其他任何内容,但请确保用户拥有准确的数据。

现在,关于实现,没有什么可以逃避上一个问题:当影响某些到期日期的事情发生变化时,您将不得不运行该过程。但是,您可以做的不是不必要地运行该过程。例如,您提到您可以在用户登录时运行它。如果有2个或更多用户登录并查看同一个项目并且不进行任何更改,该怎么办?没有必要两次运行该过程。

更重要的是,如果您确保在用户更新项目时运行该流程,则您不需要在任何其他时间运行该流程。总之,与"轮询相比,该模式具有以下优点和缺点。溶液:

<强>优点

  • 没有预定的工作
  • 没有不需要的进程运行(这是有争议的,因为您可以在项目上设置dirty标志,只有在true时才运行它。)
  • 没有dirty
  • 的不必要查询
  • 将始终通知用户项目的当前和实际状态(这是迄今为止提供的任何解决方案中最重要的项目)。

<强>缺点

  • 如果用户更新项目,然后在几秒钟内再次升级该过程,则该过程将运行两次(在轮询模式中,该过程可能甚至不会在该时间段内运行一次,具体取决于已安排的频率)
  • 更新项目的用户必须等待该过程完成

更改为以与StackOverflow类似的方式实现通知系统的方式,这是一个完全不同的问题。我想你与用户和项目之间存在多对多的关系。最简单的解决方案是为这些实体之间的关系添加单个属性(中间表):

基数:用户有很多项目。一个项目有很多用户

这样,当您运行该过程时,您应该使用新结果更新每个用户Has_pending_notifications。例如,如果用户更新了项目并且不再按时,那么您应该将true所有用户设为Has_pending_notifications字段,以便他们了解情况。同样,当项目准时时将其设置为false (我知道您只是想确保在项目不再准时时显示通知)。

以StackOverflow为例,当用户阅读通知时,您应将标志设置为false。确保您没有使用时间戳来猜测用户是否已阅读通知:登录并不意味着阅读通知

最后,如果通知本身足够复杂,您可以将其从用户和项目之间的关系中移开,并采用以下方式:

基数:用户有很多项目。一个项目有很多用户。用户有很多通知。通知有一个用户。一个项目有很多通知。通知有一个项目。

我希望我所说的有道理,或者给你一些更好的主意:)

答案 1 :(得分:6)

您可以执行以下操作:

  1. 向每个用户记录添加一个日期时间字段,表示上次完成慢速计算的时间。称之为 LastDate
  2. 为每个项目添加一个布尔值,说明是否必须列出。称之为:已选择
  3. 运行Slow程序集时,您将更新 Selected fileds
  4. 现在当用户记录 LastDate 足够接近现在时,您使用最后一次慢速计算的结果,只需使用 Selected 的所有项目为true。否则你的计算速度慢了。 上述过程是最佳的,因为它只在实际需要的情况下重新计算慢速程序,同时以固定的时间间隔运行程序......有浪费时间的风险,因为用户可能会使用计算结果。

答案 2 :(得分:3)

让字段“陈旧”。 运行更新stale = 1的SQL语句,其中所有记录的stale = 0 AND(该算法返回true)。 然后运行一个SQL语句,选择stale = 1的所有记录。

这种方法可以快速运行的原因是因为如果前半部分返回true,SQL解析器(如PHP)不应该执行AND语句的后半部分,这使得它快速运行整个列表,检查所有记录,如果没有陈旧,试图让它们陈旧。如果它已经过时,则不会执行算法,从而节省您的时间。如果不是,则运行算法以查看它是否过时,然后过时将设置为1.

然后第二个查询只返回stale = 1的所有陈旧记录。

答案 3 :(得分:0)

你可以这样做:

在数据库中,每次用户访问项目时都会更改时间戳。 当用户登录时,拉出他们的所有项目。检查时间戳并将其与今天的日期进行比较,如果它超过n天,则将其添加到陈旧列表中。我不相信比较日期会导致任何缓慢的逻辑。

答案 4 :(得分:0)

我认为在考虑数据库和代码之前需要解决基本问题。其中主要是:“为什么IsStale()慢?”

从其他地方的评论中可以清楚地看出,这种缓慢的概念是不容谈判的。这个计算不在你手中吗?结果是否抵抗缓存?什么级别的变化会触发重新计算。

过去编写过调度系统,有两种类型的更改:可能在松弛中发生的更改以及导致级联计划更改的更改。同样,有两种类型的重建:总计和本地。总重建是显而易见的;本地重建尝试尽量减少对其他计划资源的“损害”。

问题的关键在于:如果您在每次更新时都进行了全面重建,那么您可以查看从更改到计划稳定时间的30分钟滞后。 (我的基础是我在ERP系统的重建时间和非常复杂的工作量方面的经验)。

如果您的系统的实际情况是此类任务需要30分钟,那么为用户设计即时满足的设计目标与事情的基本事实背道而驰。但是,您可能能够比重建更快地检测计划不一致。在这种情况下,您可以向用户显示“计划已被超出,重新计算新的结束时间”或类似的东西......但我怀疑如果您在同一时间由不同用户输入大量计划更改,系统将降级连续显示该通知。但是,您至少可以获得以下优势:您可以在一段时间内批量更改以进行下一次重建。

正是由于这个原因,我见过的大多数调度问题实际上并没有进行实时重新计算。在ERP情况下,有一个计划主管负责车间的安排,任何变更都可以通过它们进行管理。 “主”计划在每个班次之前重新生成(轮班时间为12小时,因此每天两次),并且在班次期间,通过“本地”修改进行延迟,这些修改不会将主计划调整到下一个12小时块。< / p>

在更简单的情况下(软件设计),日程安排每天更新一次,以响应当天的进度报告。在第二天早上的scrum中传递了坏消息,以及更新的时间表。

长话短说,我想也许这是一个“毫无疑问”的时刻,这个假设需要受到挑战。如果重新计算足够大以至于连续更新是不切实际的,那么将期望与现实保持一致是有序的。要么算法需要工作(优化局部变化),硬件场需要扩展,要么需要重新校准“真相”的期望时间。

一个更精确的答案坦率地需要更多的细节,而不是“只是假设一个昂贵的过程”,因为对这个过程的正确攻击点是不可能知道的。