在 Google App Engine Datastore 中,有时需要删除对象并缓存剩余对象。然而,在使用 Python 代码时,可能会遇到这样的问题:虽然对象已成功删除,但 Python 日志和 Memcache 却无法识别删除操作。Datastore Viewer 显示对象已删除,但日志显示项目长度没有改变。此外,Memcache 仍然缓存所有项目,就像没有发生删除操作一样。
以下代码示例演示了上述问题:
yesterday = datetime.now()-timedelta(days=1) # one day ago
sessions = db.GqlQuery("SELECT * FROM MentorAvailSessions WHERE created > :1", yesterday).fetch(1000) #pulling list of all objects
logging.info('************** len before deleting a session: %s*********' % len(sessions)) # shows a length of 3
for session in sessions:
if (session.session_id == end_session_id) and (session.user == user_info.username):
session.delete();
remaining_sessions = db.GqlQuery("SELECT * FROM MentorAvailSessions WHERE created > :1", yesterday).fetch(1000) #pulling list of just the remaining objects after deleting one
logging.info('** len of remaining sessions: %s' % len(remaining_sessions)) # still shows a length of 3 after session.delete
memcache.set('mentor_avail_sessions_cache', remaining_sessions, time=50000) # is caching all three items instead of just the remaining 2
如代码示例所示,在删除对象 session
后,剩余对象的长度为 3,但日志中仍然显示剩余对象的长度为 3。并且,Memcache 仍然缓存所有对象,而不是缓存删除后的剩余对象。
2、解决方案
造成上述问题的原因是“最终一致性”。在没有祖先关系的查询中,无法保证强一致性。在开发服务器上,这种效果会被夸大,以提醒您注意这个问题,而在生产环境中,您很少会看到不一致性。
要解决此问题,有两种方法:
-
确保查询使用了祖先关系,以便它属于一个实体组。
-
可以显式地递减 Memcache 计数器,而不是从查询中刷新它。
以下是第二种方法的代码示例:
yesterday = datetime.now()-timedelta(days=1) # one day ago
sessions = db.GqlQuery("SELECT * FROM MentorAvailSessions WHERE created > :1", yesterday).fetch(1000) #pulling list of all objects
logging.info('************** len before deleting a session: %s*********' % len(sessions)) # shows a length of 3
for session in sessions:
if (session.session_id == end_session_id) and (session.user == user_info.username):
session.delete();
remaining_sessions_cache = memcache.get('mentor_avail_sessions_cache')
if (remaining_sessions_cache == None):
remaining_sessions_cache = 3
remaining_sessions_cache -= 1
memcache.set('mentor_avail_sessions_cache', remaining_sessions_cache)
在该示例中,我们首先获取 Memcache 中的当前计数器值。如果计数器值为空,则将其设置为 3(假设这是对象的初始数量)。然后,在删除对象后,我们将计数器值减 1,并将更新后的值存储回 Memcache。这样,Memcache 中的计数器将准确反映已删除对象的剩余数量。