8

我工作的公司为黑莓平台创建应用程序。

我们一直在研究一个专有的“分析系统”,它允许我们将代码嵌入到我们的应用程序中,并让应用程序在每次运行时向我们的中央服务器报告一些统计数据。目前,系统运行正常;但是它仅处于测试阶段,每小时点击 100-200 次。“命中”会毫无问题地发送到服务器。我们已经构建了一个非常可靠的 API 来处理命中的接受和存储(在 MySQL 数据库中)。我们已经测试了负载,我们应该能够毫无问题地容纳每小时数十万次点击。这不是一个真正的问题。

问题是显示统计数据。我们构建了一个类似于 Mint (haveamint.com) 的显示面板,它显示每小时、过去几天、几个月、几周、几年等的点击量。第一个版本运行直接查询,从命中表中提取数据并即时解释它。这并没有奏效很长时间。我们当前的解决方案是将命中“排队”以进行处理,并且我们每 5 分钟有一个 cron 来处理命中并将它们分类到每小时、每天、每周、每月、每年等的“缓存”中。这非常有效,并且具有令人难以置信的可扩展性;但是,它仅适用于 1 个时区。由于整个公司都可以访问它,我们正在与不同时区的数百名用户打交道。我定义的“今天” 圣何塞与我在伦敦的同事对今天的定义大不相同。由于当前解决方案仅缓存到 1 个时区,因此对于在我们的时区之外检查数据的任何人来说都是一场噩梦。

我们目前解决这个问题的计划是为每个时区创建缓存(总共 40 个);但是,这意味着我们将数据量乘以 40……这对我来说太可怕了,并且考虑到缓存可能非常大,乘以它听起来是个坏主意;另外,当我们去处理队列时,将它们放入 40 个不同的缓存中需要更多的 CPU 时间。

还有其他人对如何解决这个问题有更好的想法吗?

(对不起这么长的问题......这并不容易解释。谢谢大家!)

4

4 回答 4

4

您提出的解决方案有太多冗余。我建议您将数据存储在至少 30 分钟的存储桶中,而不是每小时存储一次,并将时区标准化为 UTC。

对于 30 分钟的存储桶,如果用户请求从 -4.5 UTC 开始的下午 1 点到下午 2 点的每小时数据,您可以从系统中获取下午 5:30 到下午 6:30 的数据并显示出来。如果您以一小时为增量存储数据,则您无法为时区的用户提供 N + 0.5 小时差异的服务请求。

对于每日数字,您需要汇总 48 个半小时时段。要选择的时段将由用户的时区决定。

当您获得年度数据时会变得很有趣,因为您最终必须汇总 17,520 个半小时的存储桶。为了简化计算,我建议您获取每个 UTC 时间的预聚合年度数据,并减去一年中第一个 4.5 小时的聚合数据,并添加下一年前 4.5 小时的聚合数据。这实际上将全年转移 4.5 小时,而且工作量并不多。从这里开始,您可以进一步调整系统。

编辑:原来加德满都是 +5.45 GMT,所以您需要将数据存储在 15 分钟的存储桶中,而不是 30 分钟的存储桶中。

编辑 2:另一个简单的改进是每年汇总一次,因此您不必每次添加 17,520 个桶,也不需要每个国家/地区的汇总。汇总 1 月 2 日 - 12 月 30 日的年度数据。由于任何两个国家之间的最大时区差异为 23 小时,这意味着您可以获取年度数据(1 月 2 日 - 12 月 30 日)并在前后添加几个桶作为适当的。例如,对于 -5 UTC 时区,您将在 0500 之后的 1 月 1 日添加所有存储桶,在 12 月 31 日添加所有存储桶,并在下一年的 1 月 1 日添加最多 0500 小时。

于 2009-04-12T17:52:45.620 回答
2

在设计涉及多个时区的软件时,我会说始终将您的日期/时间存储在UTC中,并在原始时区的另一个字段中存储一个函数,该函数可以花费时间并将其与 UTC/时区相互转换。你会为自己省去很多麻烦来处理白天切换、夏令时、人们从地球另一端查看一个国家的统计数据等不同的情况......

在您的情况下,使用 UTC 缓存并调整要转换为 UTC 的请求应该会有所帮助。不要将统计数据存储为“今天”,将其存储为 00:00:00UTC 到 23:59:59UTC 几个小时,当有人在纽约询问今天的统计数据时,进行转换。

于 2009-04-12T17:34:43.730 回答
0

据我所知,您正在这里寻找数据仓库系统的存储部分(您的报告将是前端)。

实际上,商业系统的做法是您描述的缓存:预先聚合您的表并创建它们的缓存。加速查询的唯一方法是减少数据库系统为它们做的事情。这意味着更少的数据,这反过来意味着迭代数据或索引中的数据更少的时间。

也就是说,我要么提出“40 个缓存解决方案”(真的有超过 24 个时区)。您应该能够通过创建数据副本来简单地并行化排序队列。

另一种方法是按小时粒度缓存,然后将小时聚合为天(如果您的时区需要,则聚合为 30 分钟)。这意味着您以比日常缓存更精细的粒度进行缓存,但比原始数据的粒度更粗。

于 2009-04-12T17:35:06.023 回答
0

这种数据通常使用循环或循环数据库存储。检查这个http://www.shinguz.ch/MySQL/mysql_20070223.html和这个http://techblog.tilllate.com/2008/06/22/round-robin-data-storage-in-mysql/了解如何他们工作以及如何在 MySQL 下实现它

于 2009-04-12T17:48:20.670 回答