5

我的团队需要找到解决以下问题的方法:

我们的应用程序允许用户查看企业的总销售额、产品总数、区域总数、区域 x 产品总数、区域 x 部门总数等。你明白了。有太多的值需要聚合才能得到其中许多无法即时计算的总数——我们必须预先聚合它们以提供合适的响应时间,这个过程大约需要 5 分钟。

这个问题,我们认为是一个常见的问题,但找不到参考,是如何在不关闭用户的情况下允许更新各种销售。此外,用户不能接受最终的一致性——如果他们向下钻取总共 12 个,他们最好看到加起来为 12 的数字。所以我们需要一致性 + 可用性。

到目前为止,我们提出的最佳解决方案是将所有查询定向到冗余数据库“B”(针对查询进行了优化),而将更新定向到主数据库“A”。当我们决定花 5 分钟更新所有聚合时,我们更新数据库“C”,它是另一个冗余数据库,就像“B”一样。然后,新用户会话被定向到“C”,而现有用户会话继续使用“B”。最终,警告任何使用“B”离开的人,我们终止“B”上的会话并在那里重新聚合,交换“B”和“C”的角色。典型的排水停止场景。

我们很惊讶我们找不到任何关于此的讨论,并担心我们过度设计了这个问题,或者这可能不是我们认为的问题。非常感谢任何建议。

4

3 回答 3

2

这是一个有趣的问题,所以我在火车上考虑了这个问题,并想出了在数据库中为您聚合的每一行存储时间戳的想法。(我认为这种技术有一个名字,但它逃脱了我并且谷歌搜索没有找到它......)

时间戳将指示何时插入此行。此外:

- 如果可以更新行,那么您将同时拥有该行的两个“版本”,一个比另一个更新。

- 如果可以删除行,则需要有一个“已删除版本”行来指定删除的时间。

现在您可以执行以下操作:

1) 假设您在 2000 年 1 月 1 日午夜更新聚合。您可以让表的视图返回表的数据,就好像它是 2000 年 1 月 1 日午夜一样,忽略比这更近的所有插入/更新/删除。现在聚合与视图中的数据一样是最新的,您可以继续将数据添加到基础表中。

2)我不知道保证它的可靠性有多可行/容易,但是你可以有“差分计算的聚合”,在 2000 年 1 月 2 日午夜,你取 2000 年 1 月 1 日午夜的聚合并仅使用自那时以来已更改的数据 - 使您免于重新计算如此多的历史数据。(当然,一旦您考虑更新或删除超过 24 小时的行,它就会变得更加棘手)

3)每当您更新聚合时,您可以将更新和删除的行与其旧版本合并并摆脱旧版本,因此您只需在需要时保留重复的行以分隔已被删除的行聚合和不聚合的行(这也意味着,例如,如果您的所有聚合同时运行,并且您快速连续更新一行 3 次,您只需要保留最新的更新指示行)

于 2013-05-08T22:28:18.250 回答
2

如果无法即时计算更新,那么在另一个数据库中缓存结果集有助于解决可用性问题,并加快响应时间。

为了保持一致性,您可以使用某种形式的事务隔离。例如,MySQL 支持许多不同的事务级别,其中REPEATABLE READ可能接近于在单个事务中为您提供一些一致性。如果当用户向下钻取以查看数据时,可以为多个请求打开事务,则他们实际上会看到第一个请求时数据库状态的快照。

在更一般的意义上,您只是在处理客户端提供的数据的句柄以指示一致的集合。正如在 Patashu 的回答中一样,请求一组聚合的客户端的句柄可能是基于时间的。客户端交互的第一阶段是获取最新聚合数据的句柄,例如当前时间。如果将在每个请求中传递该句柄。当向服务器发出请求时,它使用句柄来确定要返回哪一组聚合数据。所有聚合数据都可以存储在服务器“B”中,而不是同时具有服务器“B”和“C”,所有聚合数据都包含句柄信息。然后,这允许向单个服务器请求聚合新旧数据。在某些时候,旧的聚合数据可能会从“B”中清除。

也许对事务隔离的搜索会发现更多关于一致性的讨论结果。

于 2013-05-08T23:57:05.167 回答
1

我认为您正在寻找数据仓库概念

在计算中,数据仓库或企业数据仓库(DW、DWH 或 EDW)是用于报告和数据分析的数据库。它是数据的中央存储库,通过集成来自一个或多个不同来源的数据而创建。数据仓库存储当前和历史数据,并用于为高级管理报告创建趋势报告,例如年度和季度比较。

...

与基于 ETL 的数据仓库不同,集成的源数据系统和数据仓库都是集成的,因为没有维度或参考数据的转换。这种集成数据仓库架构支持从数据仓库的聚合数据向下钻取到集成源数据系统的事务数据。

于 2013-05-09T01:22:59.460 回答