代码之家  ›  专栏  ›  技术社区  ›  Patrick

推送数据更改与在应用程序中拉送数据更改

  •  4
  • Patrick  · 技术社区  · 14 年前

    假设您有一个由两层组成的应用程序:

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

    现在,数据在层A中被更改。我们有两种方法来确保来自层B的报告被正确更新。

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

    推送方法有几个缺点:

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

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

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

    如果我们有两个以上的层次,情况就会变得更加困难。假设我们有以下4层:

    • A:存储从数据库或文件加载的所有数据的数据层。
    • B:使用数据层(A层)的层,例如,使用复杂的过滤函数过滤A中的数据。
    • C:使用B层的一个层,例如将B层的数据聚合成更小的信息块。
    • D:一份解释C层结果并以图形方式呈现给用户的报告。

    在这种情况下,推动更改几乎肯定会带来更高的开销。

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

    • D层必须打电话给C层询问它是否脏
    • C层必须打电话给B层询问是否脏了
    • B层必须打电话给A层询问它是否脏

    如果什么都没有改变,那么在你知道什么都没有改变,你不必做任何事情之前,要执行的调用的数量是相当大的。似乎我们试图通过不使用push来避免的性能开销现在又回到pull方法中使用了,因为有很多调用询问是否有任何问题。

    有没有以一种好的、高性能(低开销)的方式解决这类问题的模式?

    2 回复  |  直到 14 年前
        1
  •  3
  •   djna    14 年前

    不,没有免费午餐,没有银弹。一切都取决于精心设计。你已经介绍了很多常用的技术,它巧妙地应用了它们,这需要注意和避免假设。

    我查询了你的两个陈述:

    您意味着控制推送通知是非常困难的。我本以为在很多情况下,你会有一个主计算引擎,它可以获取数据并进行计算。引擎一定要在某一点停止,此时它可以发送“新数据就绪”事件,该事件可以包含有关更改内容的更细粒度的信息。

    你说打4个层间电话太贵了。它的基础是什么?与什么相比?如果你关心的是多重因素(10个D实例)调用(5个C实例)调用(2个B实例)调用(1个A实例),所以A被100个调用击中,那么我们肯定会优化?每个级别都可以说“如果我现在正在打电话或者最近听到了答案,就不需要再打电话了”。

    当我们考虑层的伸缩性好处时,一些便宜的查询可能不会太多。

        2
  •  0
  •   Tim Williscroft    14 年前

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

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

    (消费者有一个依赖逆转。)

    这使得所有数据流管道在粘合代码中都显式地显示出来。 订阅可以提前设置,因此conusmers不需要知道如何工作。

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