【问题标题】:Appengine ndb best optimal way to design top downloads per day, week, monthAppengine ndb 设计每天、每周、每月最高下载量的最佳方式
【发布时间】:2017-06-10 15:30:48
【问题描述】:

您好,我正在构建一个简单的电影网站,并且我使用谷歌数据存储作为我的后端。

我需要设计每天、每周、每月、所有时间的顶级电影下载量。

现在我只跟踪下载次数,例如:数据库就像一部电影的单行,其中 num_of_downloads 作为一列,每当用户下载电影时,我都会增加该字段。

Movie Id | Title | Description | num_of_downloads

现在,什么是显示每天、每周、每月、所有时间的热门电影下载量的最佳最佳方式。

我正在考虑实现一个带有电影键和日期字段的新表,以跟踪每天的下载次数,我可以用它来计算其余问题。

Movie ID, Date,      Downloads
M1        01/01/2017  1000
M2        01/01/2017   100
M1        02/01/2017  2000

我不确定这是设计 appengine 数据存储的最佳方式,同时编写查询以获得本周前 10 名的下载量,因为它不像 sql 查询那么容易。

【问题讨论】:

    标签: python google-app-engine database-design google-cloud-datastore nosql


    【解决方案1】:

    如果您希望总数 100% 正确,那么在数据存储中解决这个问题并不容易。涉及手动更新此类计数器。

    对于您的情况,更好的方法是在您处理这些请求时将下载数据导出或流式传输到 bigquery 或 google 分析。然后,一个每日 cron 可以计算统计数据并将它们缓存在数据存储或 memcached 之类的地方。

    分析是免费的,但统计数据并不准确。 Bigquery 有成本,但就您而言,它们的成本很低,因为它主要是存储(便宜)和每天 3 个查询(便宜)

    【讨论】:

    • 您好 Zig,感谢您的回复,您最初想从 google 分析中获取数据,但它不能按时准确,因为这取决于 cron 作业何时从 GA 获取数据并通勤。此外,如果我们有更多数据,那么采样将是一个问题。有没有其他最佳方式来设计和解决问题??
    • 另一种方式已经在我的回答中。我写了两个选项,
    【解决方案2】:

    数据存储非常有限,不能很好地匹配统计信息。我同意 Zig 的观点,您应该使用替代服务来解决这个问题。

    我建议您简单地使用 Cloud SQL 并为每部下载的电影保留一个记录,并将您获得的所有信息添加到该记录中。由于这与下载电影的数量有关,因此数量将受到限制。只要您使用正确的索引和缓存,我很难想象这会导致任何延迟、定价或配额问题。

    如果您想向我们的用户显示更多指标,或者如果您希望将其用于内部目的,那么在 sql 中提供所有可用信息可能会派上用场。

    【讨论】:

    • 您好,感谢 Arne 的回复,但是否可以存储所有信息,例如:电影名称、no_of_downloads、每次从 appengine 下载到云 sql 的时间戳?我认为这会是开销,因为每当下载电影时,我们都会收到对 appengine 更新 counter_value 的请求,如果我们要使用云 sql,那么我们需要插入一条带时间戳的记录,如果电影下载 10K 次,就会是 10K 记录和 1000 部电影,它将跨越 1000 万行
    • Wen 计划构建一个可以处理 1000 万次电影下载的东西,跟踪每次下载不会成为成本和复杂性方面的问题。如果您想要的只是能够在设定的时间间隔内计算下载次数,您可以在不维护有关每部下载电影的信息的情况下做到这一点。但是,由于维护正确记录的成本可以忽略不计,而收益却很大,因此这确实是明智之举。
    • 云 sql (mysql) 的 10m 行应该不是问题参考 stackoverflow.com/a/5351306/1010991。您可能应该进行某种程度的标准化(movie_name = movie_id)并跟踪 user_id、客户端平台等。
    • 是的,我几乎能够得到您的解决方案,我认为维护每条记录将为我们提供大量信息以供将来进行数据分析。这是成本与存储和计算之间的权衡。但是,如果我们可以使用数据存储而不是云 sql 来维护记录呢??
    【解决方案3】:

    我将对其他两个答案提出不同意见,并提出可能的应用引擎解决方案。

    创建一个实体来累积每天的统计数据:

    class MovieStats(ndb.Model):
        day = ndb.DateTimeProperty()
        movies = ndb.KeyProperty(repeated=True)
    

    然后,您为每个电影下载更新当天的 MovieStats 实体。当然,您需要对事务执行此操作,并以避免争用的方式执行此操作。一种解决方案是分片计数器,但我非常喜欢 Nick Johnson 在两篇博文中描述的解决方案:

    我不想在这里重复这些帖子,但基本思想是,对于每次下载电影,您都将一个任务添加到拉取队列以更新电影的计数器。然后,每分钟一次(或其他时间间隔),您处理拉取队列中的所有任务并在事务中更新您的MovieStats 实体。

    为了处理拉取队列任务,您可以有一个每分钟启动一次的 cron 作业,或者使用上述“按需”CRON 作业。每次将任务添加到拉取队列时,都会创建一个工作任务(常规推送队列)来处理拉取队列中的任务。对于工作任务,您添加一个与时间间隔相对应的任务名称,以确保您在该时间间隔内只有一个工作任务。它可以让您获得 1 分钟 CRON 作业的好处,但额外的性能奖励是它只在需要时运行,因此您不需要在不需要时运行 CRON 作业。

    【讨论】:

      猜你喜欢
      • 2011-07-20
      • 2011-05-30
      • 2011-09-22
      • 2017-09-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多