【发布时间】: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