【问题标题】:AppEngine real time querying - cost, performance, latency balancing act and quotasAppEngine 实时查询 - 成本、性能、延迟平衡行为和配额
【发布时间】:2014-03-23 08:34:21
【问题描述】:

我正在尝试设计一个应用,它使用 Google AppEngine 来存储/处理/查询数据,然后通过 Cloud Endpoints API 尽可能实时地将数据提供给移动设备。

这是一个足够直截了当的解决方案,但我正在努力在 AppEngine 的性能、成本和延迟之间取得适当的平衡。

场景(类比)是用户签到(每天从不同地点、城市、国家多次签到),我们希望允许用户通过他们的设备查询所有数据并提供最新信息尽可能。

  • 如:
    • 最近签到次数:
    • 24 小时
    • 1 周
    • 1 个月
    • 所有时间
    • 在同一时间段内检查最多的地方/城市/国家/地区是哪里
    • 在同一时间段内检查最少的地方
    • 其他类似的查询报告

我们可以使用 Memcache 来存储最近的签到,每 5 分钟推送到数据存储区,但这可能无法很好地扩展并且不够健壮! 使用 Cron 作业运行任务队列/Map Reduce,以每 30 分钟获取每个位置的聚合、平均值并更新数据存储。

挑战在于在数据存储上使用尽可能少的读/写,因为最近的“24 小时”数据每 5 分钟更改一次,因此最近几周的数据、最近几个月的数据等等也是如此。数据在某种程度上必须是动态的,所以它不是固定的时间点,它们总是在变化 - 这就是问题所在!

设置它不是问题,但要以有效的方式设置它,平衡用户的性能/延迟和我们的成本/配额并不是那么容易!

简单的解决方案是使用 SQL,并运行日期范围查询,但这不会很好地扩展。

我们最终可以使用 BigTable 和 BigQuery 进行“所有时间”时间段查询,但要通过 API 为用户提供尽可能实时的其他时间段数据,这证明是一个很大的挑战!

我们非常欢迎任何关于 AppEngine 架构/方法的建议。

非常感谢。

【问题讨论】:

    标签: python google-app-engine mapreduce task-queue


    【解决方案1】:

    Push Queue 在添加新签入方面比 Memcache 更强大。 Memcacheget_entity_group_version(key) 一起减少读取量。

    提前从每日、每周、每月和每年维度的用户历史中汇总统计数据(例如最受欢迎和最不受欢迎的位置),以减少查询记录数(与分析数据库一样)。设计您的实时查询,以便将过去存储的聚合数据与您尚未聚合的少量当前数据合并。

    【讨论】:

    • 非常感谢 Martin 的建议和链接,非常感谢,那里有一些好的点,会研究它们。
    【解决方案2】:

    首先,写入数据存储需要几毫秒。当您的用户点击刷新按钮(或您提供的任何内容)时,数据将尽可能“实时”。

    通常情况下,当存在同步/拥塞问题时,开发人员会关注实时性,即每个用户都可以更新某些内容(例如,对某个项目的出价),并且所有用户都必须获得相同的数据(最高出价)即时的。在您的情况下,如果用户获得 1 秒前的签到次数会有什么危害?

    其次,Memcache 中的数据随时可能丢失。在您提出的解决方案中(每 5 分钟更新一次数据存储),您可能会丢失 5 分钟内的所有数据。

    我宁愿在相反的方向使用 Memcache:从数据存储中读取数据,将其放入 Memcache 并在 60 秒(或更长时间)过期后从 Memcache 为所有用户提供服务,然后刷新它。这将最大限度地减少您的阅读量。当然,我会这样做,除非您的用户绝对必须知道过去 60 秒内发生了多少签入。

    对您来说真正的问题是如何对数据进行建模以优化写入。如果您不想丢失数据,则必须在数据存储中记录每次签入。您可以通过确保没有不必要的索引字段、将经常更新的字段与其他字段分开等来保存。

    【讨论】:

    • 嗨,Andrei,感谢您的反馈,您提出了一些很好的观点,并且在大多数观点上倾向于同意您的观点 - 您如何看待将文本文件推送到包含全球数据的用户设备,所以当他们查询那方面的事情时,他们会通过他们的设备进行数字运算吗?然后我们每 30 分钟推送一个新的更新文件——我知道这与实时方法非常不同,但只是一个想法——这很愚蠢吗?
    • 我不确定这种方法的可扩展性如何。随着数据量的增长,文件大小会增长,处理时间会成倍增长。使用数据存储,您可以获得有保证的性能。
    • 还有 Andrei,当您说“将经常更新的字段与其他字段分开”时,您的意思是什么——您的意思是规范化数据吗?或者说不需要自定义索引?
    • 索引越少越好,但主要好处是写入成本。每次更新实体时,都必须重新编写每个属性。对于索引属性,这意味着额外的成本。因此,如果您有用户记录,例如,姓名、出生日期、状态、电子邮件等字段不会经常更改,而“积分”等字段可能每隔几分钟就会更改一次。在这种情况下,您希望将“points”属性放入单独的实体中以降低写入成本。
    • 有道理安德烈,感谢澄清。我知道您提到可能以与我建议相反的方式使用 Memcache,这又完全有道理,我想知道您是否听说过 Pulse 的 linkLivecount?这就是给我的想法,所以可能会尝试吗?
    猜你喜欢
    • 2010-10-08
    • 2022-07-23
    • 2013-12-19
    • 2011-06-12
    • 1970-01-01
    • 2017-03-21
    • 2013-06-11
    • 2011-10-16
    相关资源
    最近更新 更多