是否有通过互联网处理大型数据集的设计模式?

时间:2009-11-03 21:45:27

标签: c# wcf silverlight design-patterns silverlight-3.0

我正在寻找一种通过互联网处理大型数据集的设计模式,并定期更新这些对象。我正在开发一个应用程序,它将一次在UI中显示数千条记录。此外,这些对象上的各种属性非常短暂,需要在客户端上进行更新,以使用户了解系统中这些记录的更改状态。我有一些想法如何处理这个问题,但想到可能有一个处理这种情况的设计模式(或模式)。

限制:

  1. 客户端用Silverlight编写。
  2. 对象本身不是很大(大约15个值类型和字符串属性),但查询所有数据是很昂贵的。大约15个属性包含来自各种来源的数据;没有聪明的连接语句或索引可以加快查询速度。我想在初始加载时只填充属性的一部分,然后在用户放大给定的对象分组时填充更昂贵的细节。想想谷歌地图,但不是街道和建筑物,而是显示对象。
  3. 我将能够限制正在更新的数千个对象的部分。但是,我需要用户能够“缩小”允许粒度更新的上下文,以显示所有数千个对象。我想当对象离开足够的缩放上下文时,将再次禁用更新。
  4. 如何解决全部或部分问题的想法?就像我提到的那样,我已经考虑了一些想法,但到目前为止,我所做的一切都没有让我对这个项目的成功有一个很好的感觉。

    修改

    我认为困难的部分真的归结为两件事,我可能需要两种截然不同的模式/做法/策略:

    1. 通过互联网加载大量记录(~5k)。
    2. 保持这些对象的子集(~500)通过互联网更新至今。
    3. 有几种设计模式可用于其他一切。

      编辑2:

      感谢Silverlight中各种“推送”实现的链接。我可以发誓套接字已从Silverlight中取出,但根据下面的答案找到了Silverlight 3参考。这对我来说真的不是一个大问题,而且我没有花太多时间研究,所以我正在编辑原始文本。无论是通过民意调查还是通过推送进行更新,一般的设计问题仍然存在。很高兴知道我有选择。

      编辑3:推动技术的后续行动。

      我怀疑Silverlight WCF双工实现是comet-like push。这不会扩展,并且有很多关于它在现实世界中如何不存在的文章。

      Silverlight中的套接字实现以多种方式瘫痪。看起来它在我们的场景中将毫无用处,因为Web服务器可能位于任何给定的客户端防火墙之后,不允许非标准端口,并且Silverlight套接字将无法连接到80,443等。

      我仍在考虑以某种有限的方式使用WCFduplex方法,但看起来轮询将成为答案。

      编辑4:找到解决问题一半的模式

      我找到了 this pattern (PDF) ,它说明了使用迭代器模式从服务器检索数据页并将它们显示为一个简单的迭代器。在.Net中我想象这将实现为IEnumerable(示例代码在Java和Oracle SQL中)。我特别感兴趣的是异步页面预取,基本上缓冲结果集客户端。使用5k对象时,所有内容都不会同时出现在屏幕上,因此我可以使用一种策略,即不会立即获取所有内容,而是从UI隐藏实现细节。应用程序将检索的核心对象位于数据库中,然后需要其他查找才能完全填充这些对象。这种方法似乎是一种快速将一些数据输出到客户端的好方法。

      我现在正在考虑使用这种模式+某种代理对象模式,它监听结果集的增量并相应地更新对象。这里可以采取一些策略。我可以预先加载所有数据,然后发送更改的增量(这可能需要子系统中的一些额外代码来提供更改通知)。这可能是我的第一种方法。我还在寻找。感谢到目前为止的所有想法。

8 个答案:

答案 0 :(得分:2)

proxy design pattern是有助于将数据从一个点传输到另一个点的模式。代理设计模式将允许您将远程对象视为本地对象。

答案 1 :(得分:2)

2提出的解决方案可以

1)压缩你的收藏并在转移后解压缩。

2)使用Flyweight +代理模式。

答案 2 :(得分:2)

我想知道你是否可以减少首先进入客户端屏幕的数据量?无论如何,您无法同时看到5,000个数据点。如果您需要滚动查找重要内容,请考虑过滤掉不重要的内容。考虑一些UI设计(仪表板和仪表类型的东西),以便用户只看到故障点。然后他们可以根据需要钻取并采取行动。

我知道你无法透露细节而且我做了很多假设,这不是你问题的直接技术答案 - 但是重新思考必要的数据源可以帮助你更有效地推动两者后端和前端。

答案 3 :(得分:1)

在这里,我发现了一篇文章,似乎解释了如何在Silverlight 2中创建套接字 Silverlight 2 and System.Net.Sockets.Socket

我没有深入阅读(这对我来说有点太晚了),但它似乎可以在你的情况下使用。我看到的主要限制是你的silverlight应用程序只能连接到它下载的服务器。

这是关于第9频道Silverlight using socket

的教程

我希望这会有所帮助

答案 4 :(得分:1)

总的来说,我认为你的问题的答案是没有一个或多个设计模式可以真正解决你的问题。相反,这是一个大规模应用程序的一个很好的例子,它只需要大量的规划和设计工作。

当你进行设计时,我认为你会遇到一些可能在很小的层面上帮助你的DP,但是这个巨大的东西应该如何工作的细节更多的是一般的(和有趣的)设计问题。

或许稍微澄清一下您的问题可能有助于引导人们就该系统的整体设计提出建议。此外,一旦你设计/努力想出一个如何运作的高级设计,你可以要求批评/建议。作为StackOverflow问题的答案,有人完全想出这个很难。 :)

答案 5 :(得分:1)

如果我理解正确,这里确实存在两个问题:

  1. 系统状态由来自多个数据源的数据表示。因此查询州是昂贵的。
  2. 描述系统状态的数据量很大。结果查询描述状态的所有数据都很昂贵。
  3. 解决这些问题的标准模式是引入中间层并使用增量来更新状态。 E.g:

    1. 显然,您不希望Silverlight客户端直接与后端系统通信。这不仅可能是不可能的,而且效率也非常低,因为每个客户端都可以询问有关其状态的相同数据源。为了避免这种标准解决方案,需要引入一个中间层来聚合来自所有后端数据源的数据,并为客户端提供通用接口。因此,后端数据源将仅根据需要进行轮询(可以根据中间层中的每个数据源进行配置),并且客户端也不必处理这些备份数据源的细节。此外,您可以根据客户端最常见的查询实现中间层数据的索引。

    2. 假设每条记录都有ID,客户端应该只请求自上次更新以来的增量。许多模式之一是使用时间戳。例如。当客户端初始化时,它请求系统状态,中间层发送该状态,带有时间戳。当客户端需要更新某些记录时,它会在请求中提供ID,以及上次更新的时间戳。因此,中间层将仅发送自上一个时间戳以来的更改,并且仅针对请求的ID。如果object有15个属性,并且自上一个时间戳以来只更改了3个属性,则update将仅包含这3个属性的值。

    3. 至于推送与民意调查 - 推送不是自动的最佳解决方案。这实际上归结为客户需要更新的频率与客户端/中间层之间的流量之间的权衡问题。例如。如果状态变化频繁但很稀疏(例如,一次只影响几个属性),并且不需要立即更新客户端的状态,客户端可能更喜欢更改累积而不是接收每个更新,因此轮询更可取。

答案 6 :(得分:0)

我认为你可能会遗漏一些东西:因为Silverlight 3能够将数据推送到客户端。 Here这篇文章可能对此有所帮助。

答案 7 :(得分:0)

我投了几个好的答案,但提出了一个解决方案,对后端数据进行了一些更改,以及从Silverlight检索数据的新方法。以下是解决此问题的方法:

  1. 我使用bean来表示大数据图。这删除了很多传输XML。我只关心数据的一个子集,尽管它是一个相当重要的子集。通过将数据展平为bean我认为我已将序列化对象大小减少到原始对象图的大约20-25%。
  2. 后端的几乎所有数据现在都有一个字段,用于上次修改它。我能够获得所有大数据。有一些数据不会有这个,但是解决了查询性能和数据聚合的真正问题。作为其他人的一般解决方案,看起来在许多DBMS中实现起来相当简单。
  3. 我正在编写新的API来检索在提供的DateTime之后更新的数据。这允许我仅从后端系统查询新的和更改的对象(这是调用这些API的Web服务,Silverlight正在调用Web服务)。
  4. 聚合Web服务中的更改,并检测数据图的一部分是否已更改。为简单起见,如果有任何变化,我只发送整个数据图。这实际上是最难解决的问题。数据图的一部分可能有新的更新时间,但图表的核心对象尚未更新。我最终必须编写API来查找子对象的更改,然后使用API​​来查找基于这些子对象的根对象(如果它们已被更改)。可以返回一个对象图,其中包含自上次轮询以来尚未更新的根对象(实际上是对象图的大部分)。 Web服务逻辑正在查询少量更改,因此即使查询单独不便宜,它们也可能每次轮询只运行几次。即使在我们产品的大型安装中,此查询循环每个轮询周期也只运行10或20次(请参阅下面的我的轮询解决方案)。虽然我们的系统非常动态,但 在30秒内发生了很大的变化。处理所有这些的Web服务调用对初始加载调用的反应与它进行轮询时的响应相同。它所关心的只是检索比给定时间更新的数据。
  5. 我编写了一个继承自ObservableCollection的集合,用于处理查询和轮询。使用此集合的客户端代码提供了一个查询数据的委托。日期以异步方式返回,并以页面形式返回。我还没有确定页面大小。它不断重新查询页面,直到服务器返回小于最大页面大小的页面。该集合还提供了有关如何确定集合中最新对象的最新日期的信息。它会定期轮询比集合中最新项目更新的更新。实际上,这个“最新日期”实际上是一个包含原始对象图的各个部分的几个日期的对象。如果项目从集合中存在的服务器返回,则集合中的项目将使用返回的数据进行更新。我这样做了,而不是插入新项目并删除旧项目,因为它适用于更多数据绑定情况。
  6. 这种模式可以改进。我只能向Silverlight发送增量以进行更改。我仍然可以尝试使用某种推送技术。但是这个解决方案给了我一个Web服务调用,可以返回各种情况的数据。轮询也很简单,所有数据检索只有一件事。没有很多活动部件。它在初始数据加载期间和轮询期间通过相同的机制处理对象状态更改。这似乎也很好。初始调用似乎是最昂贵的,后续调用运行得越来越快。我认为这是因为每次传递后,后端剩余的数据越来越小。

    我仍然有一个关于I have posted here实施此问题的问题。

    感谢所有建议。虽然我没有注意到所有的建议,但是有些想法或者直接帮助了我,或者让我的思想在不同的道路上思考如何使其发挥作用。