【问题标题】:Caching query results on GAE在 GAE 上缓存查询结果
【发布时间】:2015-08-07 11:45:45
【问题描述】:

我在 3 个月前开始使用 Google App Engine,我在memcaching 上有一个关于 Python 的问题。 我尽量描述我的问题。

我使用ndb (App Engine Datastore),我有一个这样的实体“表”:

class Event(ndb.Model):
    dateInsert = ndb.DateTimeProperty(auto_now_add=True)              # Inserting date
    notes = ndb.StringProperty(indexed=False)                         # event notes
    geohash = ndb.StringProperty(required=True)                       # Coordinates geohash 
    eventLatitude = ndb.FloatProperty(indexed=True, required=True)    # self explanatory
    eventLongitude = ndb.FloatProperty(indexed=True, required=True)   # self explanatory

客户端(例如,使用移动应用程序)用户可以在数据存储中存储指定坐标的事件。 这些插入的事件当然可以通过移动应用程序(在地图上)和网站上看到。 现在要检索存储的事件,客户端调用一个 Web 方法来搜索给定位置附近的事件:

class getEvents(webapp.RequestHandler):
    def get(self):
        #blablabla get passed parameters
        #[...]

        # hMinPos and hMaxPos are hashed coordinates passed by client + X meters. 
        # In this way I can filter stored events in a precise bounding box.
        # For example, I can get events near my location in a box of 5000 meters
        qryEvent = Event.query(ndb.AND(Event.geohash >= hMinPos, Event.geohash <= hMaxPos))
        events = qryEvent.fetch(1000)

然后我必须使用循环循环获取每个结果以创建 JSON 以存储在列表中并将其返回给客户端。 原来如此

for event in events:
    #do my stuff

一切正常,但最大的问题是我每次调用该方法时都会进行无用的读取操作。 我的意思是,每次调用方法时,它都会获取与其他客户端请求相同的事件,或者最糟糕的是,与同一客户端之前的请求相同的事件(如果我移动 50 米并发出客户端请求,事件与之前的请求广告相同 99% )。 这将很快使配额使用和读取操作超出配额。 我想我应该使用memcache 来存储获取的事件并在从数据存储区读取之前将它们读取到内存缓存中,但我不知道用我的结构来实现它。

我的想法是使用 geohash 作为 memcache 键,但我无法遍历缓存的元素,我只能对给定键进行精确获取,因此我的解决方案不适用(我无法直接访问要使用 key 进行 memcache,我需要迭代 memcache 元素以找到适合我的坐标范围请求的事件)。 有人有提示或建议吗?

【问题讨论】:

  • 你知道 ndb 已经做了two levels of caching 吗?您是否更担心实体的查询或获取?我建议您查看Cloud Trace,看看哪些 RPC 对您的影响最大。
  • 感谢您的回复。现在我最大的问题是限制从数据存储中读取,所以我担心实体获取......无论如何我看看提供的链接!
  • 查询不会发生使用 ndb 的缓存。只有get的。你可以采取一些策略。缓存查询结果一旦转换为您自己的 json 或执行仅键查询并执行 get_multi 并让 ndb 为您缓存项目。
  • 您自己在 JSON 结果级别进行的任何缓存都意味着您需要考虑缓存失效策略,这取决于您需要信息的准确性以及您期望新兴趣点的频率添加匹配查询。
  • 没错,我知道这一点。我的解决方案应该是从 db 中获取一个 keys_only,然后在缓存中查找。如果某些键不在缓存中,我将在缺少键的数据库上执行 query_multi,然后将它们添加到缓存中。返回列表将(应该)是缓存和从数据库中检索的总和。

标签: python google-app-engine memcached google-cloud-datastore


【解决方案1】:

我能想到 2 个解决方案:

1) 在 memcached 中存储较小框(例如 100 米长)的信息,并带有经纬度标识符。您可以向 ndb 请求一大盒例如5500米长,并将所有包含的小盒子的信息保存在memcached中。当用户移动 50、100 或 400 米时,您将能够使用 memcached 数据给她一个答案,如果有人靠近那个地方(500 米内),也会发生同样的事情。

2) 您可以使用 ElasticSearch,特别是 Geo Distance Filter。有了它,你可以过滤"documents that include only hits that exists within a specific distance from a geo point"

注意:如果getEvents返回一个5000米的盒子里的事件,也许你在移动50米时不应该触发新的请求,而是更远的距离。

【讨论】:

    猜你喜欢
    • 2018-04-13
    • 1970-01-01
    • 2017-08-11
    • 2011-06-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-07
    • 2012-04-18
    相关资源
    最近更新 更多