【问题标题】:Pushing data changes vs. pulling data changes within an application在应用程序中推送数据更改与拉取数据更改
【发布时间】:2010-10-29 12:33:10
【问题描述】:

假设您有一个包含两层的应用程序:

  • 答:存储从数据库或文件加载的所有数据的数据层
  • B:在漂亮的用户界面中显示数据的层,例如图形报告

现在,A 层中的数据发生了变化。我们有 2 种方法来确保正确更新 B 层的报告。

第一种方法是 PUSH 方法。 A 层通过观察者通知 B 层,因此 B 层可以更新其报告。

PUSH 方法有几个缺点:

  • 如果数据被多次更改(例如,在加载期间或在更改大量数据的算法中),观察者会被执行多次。这可以通过引入一种缓冲来解决(防止在您仍在更改时调用观察者),但这可能非常棘手,并且经常忘记进行正确的缓冲调用。
  • 如果更改了大量数据,观察者调用可能会导致应用程序无法接受的开销。

另一种方法是 PULL 方法。 A 层只记住哪些数据被更改并且不发送任何通知(A 层被标记为脏)。在用户执行操作(可能是运行算法或加载文件或其他)之后,我们检查所有用户界面组件,并要求它们自行更新。 在这种情况下,层 B 被要求更新自身。首先,它将检查其任何底层(A 层)是否脏。如果是,它将获取更改并自行更新。如果 A 层不脏,则报告知道它无事可做。

最佳解决方案取决于具体情况。在我的情况下,PUSH 方法似乎要好得多。

如果我们有超过 2 层,情况会变得更加困难。假设我们有以下 4 层:

  • 答:存储从数据库或文件加载的所有数据的数据层
  • B:使用数据层(A 层)的层,例如使用复杂的过滤函数过滤来自 A 的数据
  • C:使用 B 层的层,例如将 B 层的数据聚合成更小的信息片段
  • D:解释 C 层结果并以精美的图形方式向用户呈现的报告

在这种情况下,推送更改几乎肯定会引入更高的开销。

另一方面,拉取更改需要:

  • D 层必须调用 C 层来询问它是否脏
  • C 层必须调用 B 层询问是否脏
  • B 层必须调用 A 层来询问它是否脏

如果什么都没有改变,那么在你知道实际上什么都没有改变并且你不需要做任何事情之前执行的调用量是相当大的。看起来我们试图通过不使用 PUSH 来避免的性能开销,现在又重新用于 PULL 方法,因为有很多电话询问是否有任何脏东西。

是否存在以良好且高性能(低开销)的方式解决此类问题的模式?

【问题讨论】:

    标签: design-patterns language-agnostic architecture


    【解决方案1】:

    没有。没有免费的午餐,没有灵丹妙药。这一切都归功于精心设计。您已经涵盖了很多常见的技术,它巧妙地应用了这些技术,需要注意并避免假设。

    我查询了你的两个陈述:

    您暗示控制 PUSH 通知非常困难。我原以为在许多情况下,您倾向于拥有一个主计算引擎,它可以抓取数据并进行计算。引擎必须在某个时间点停止,然后它可以发送“新数据就绪”事件,该事件可以包含有关更改内容的更细粒度的信息。

    您说进行 4 次层间调用太昂贵了。这样做的依据是什么?与什么相比?如果您担心乘数因子(10 个 D 实例)调用(5 个 C 实例)调用(2 个 B 实例)调用(1 个 A 实例)所以 A 被 100 个调用击中,那么我们肯定会优化吗?每个级别都可以说“如果我正在打电话或者我最近听到了答案,不需要再打电话”。

    当我们考虑层的扩展优势时,一些廉价查询可能并不过分。

    【讨论】:

    • 我没有几个实例;我有数百万个实例。但是你的回答让我意识到了一些重要的事情。推送更改通常在实例级别执行(每个实例更改都可能向前推动更改),而拉更改则在层级别执行(因为无论实例数量如何,每个层都只需拉一次)。这意味着拉可能比推快得多(至少在我的情况下)。感谢您的提示。
    • 通过实例我指的是报告过程,Ds,而不是数据项的数量。你没有一百万个D是吗?如果是这样,那我印象深刻。
    【解决方案2】:

    通过数据管理器推送,并压缩在不到 n 纳秒内发生的更改。 数据管理器实现发布-订阅。

    这意味着数据生产者只依赖于数据管理者,而数据消费者只获得数据。

    (消费者的依赖关系反转。)

    这使得所有数据流管道在您的胶水代码中变得明确。 订阅可以提前设置,因此消费者不需要知道它是如何工作的。

    数据管理器可以使用它自己的线程来调用订阅者通知,这将生产者与消费者巧妙地分离。 您可以轻松压缩更改,因为数据管理器仅使用 1 个线程进行通知,它可以通过计时器“通知”,当它唤醒时,它只看到最新状态。

    【讨论】:

      猜你喜欢
      • 2018-01-14
      • 2013-10-03
      • 2020-03-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-31
      • 1970-01-01
      相关资源
      最近更新 更多