我的团队需要找到解决以下问题的方法:
我们的应用程序允许用户查看企业的总销售额,按产品划分的总数,按地区划分的总数,按地区x产品划分的总数,按地区划分的总数等。您可以了解相关信息。有很多值需要聚合才能获得许多无法动态计算的总数 - 我们必须预先聚合它们以提供合适的响应时间,这个过程大约需要5分钟。
我们认为这个问题很常见,但却找不到引用的问题,即如何在不关闭用户的情况下允许更新各种销售。此外,用户无法接受最终的一致性 - 如果他们总共向下钻取12个,他们最好看到总数为12的数字。因此,我们需要一致性+可用性。
到目前为止,我们提出的最佳解决方案是将所有查询都指向冗余数据库," B" (针对查询进行了优化),同时将更新定向到主数据库," A"。当我们决定花5分钟来更新所有聚合时,我们更新数据库" C",这是另一个冗余数据库,就像" B"。然后,新的用户会话被定向到" C",而现有的用户会话继续使用" B"。最后,警告任何人使用" B",我们会杀死" B"并在那里重新聚合,交换" B"和" C"。典型的排水停止情景。
我们感到惊讶的是,我们无法找到任何关于此的讨论,并担心我们过度设计这个问题,或者它可能不是我们认为的问题。任何建议都非常感激。
答案 0 :(得分:2)
这是一个有趣的问题,所以我在火车上考虑过这个问题,我想出了为汇总的数据库中的每一行存储时间戳的想法。 (我认为这种技术有一个名字,但它逃脱了我,谷歌搜索没有找到它...)
时间戳将指示何时插入此行。另外:
- 如果可以更新行,那么您将同时拥有该行的两个“版本”,一个比另一个更新。
- 如果可以删除行,则需要有一个“删除版本”行,用于指定删除的时间。
现在你可以做以下事情:
1)假设您在2000年1月1日午夜更新聚合。您可以拥有该表的视图返回表的数据,就好像它是2000年1月1日午夜,忽略所有插入/更新/删除更新。现在,聚合与视图中的数据一样是最新的,您可以继续向基础表添加数据。
2)我不知道多么可行/容易保证这是可靠的,但你可以有'差异计算聚合',在2000年1月2日午夜,你采取2000年1月1日午夜的聚合并更新它们仅限于自那时以来已更改的数据 - 从而无需重新计算如此多的历史数据。 (当然,一旦考虑更新或删除超过24小时的行,它会变得更加毛茸茸)
3)每当您更新聚合时,您可以将更新和删除的行与其旧版本合并,并删除旧版本,因此您只需要在需要它们分隔行时保留重复的行已经聚合的行和没有的行(这也意味着,例如,如果所有聚合一次运行,并且您快速连续三次更新行,则只需要保留最新的更新指示行)
答案 1 :(得分:2)
如果无法动态计算更新,那么在另一个数据库中缓存结果集有助于解决可用性问题,并缩短响应时间。
为了保持一致性,您可以使用某种形式的事务隔离。例如,MySQL支持许多不同的事务级别,其中REPEATABLE READ可能接近于在单个事务中为您提供一些一致性。如果在用户向下钻取以查看数据时可以为多个请求保持打开事务,则他们会在第一个请求时有效地看到数据库状态的快照。
在更一般的意义上,您只是在客户端提供的数据句柄之后指示一致的集合。正如在Patashu的回答中,请求一组聚合的客户端的句柄可能是基于时间的。客户端交互的第一阶段是获取最新聚合数据的句柄,例如当前时间。如果然后将随每个请求传递该句柄。当请求由服务器发出时,它使用句柄来确定要返回的聚合数据集。所有聚合数据都可以存储在服务器“B”中,而不是同时具有服务器“B”和“C”,所有聚合数据都包含句柄信息。然后,这允许向单个服务器请求新旧聚合数据。在某些时候,旧的汇总数据可以从“B”中清除。
也许对事务隔离的搜索会产生更多结果,以便讨论一致性。
答案 2 :(得分:1)
我认为你正在寻找Data Warehousing概念
在计算中,数据仓库或企业数据仓库(DW,DWH, 或EDW)是用于报告和数据分析的数据库。它是一个 通过集成数据创建的中央数据库 一个或多个不同的来源。 数据仓库也存储当前数据 作为历史数据,用于创建趋势报告 高级管理层报告,如年度和季度比较。
...
与基于ETL的数据仓库不同,是集成的源数据 系统和数据仓库都是集成的,因为没有 维度或参考数据的转换。 此综合数据 仓库体系结构支持从聚合数据向下钻取 数据仓库到事务数据的集成 源数据系统。