我一直在使用App Engine几年,似乎一次又一次与HDR一起弹出的问题是,当您在一个屏幕上更新数据时,您将有时如果只读请求是在更新的一两秒内完成的,则会在该屏幕的只读版本上检索旧数据。我知道这已被讨论here和here。我知道问题是什么,但我想知道适当的解决方案可能是什么?这是一个我可以在哪里陈旧数据的例子。谷歌App Engine保存并避免获取旧数据
假设您构建购物清单应用程序。
Entity 1: ShoppingList
Entity 2: ShoppingListItem
ShoppingList实体上有一个字段,用于保存列表中的总量项目。第二个实体是您的ShoppingListItem。当您添加或删除ShoppingListItem时,您需要更新ShoppingList上的总数。你有两种方法来更新总数。
- 查询数据库并统计ShoppingListItem表中的项目数。
- 自动递增缓存的总字段+/- 1,而不需要统计数据库。
有了这两种解决方案,您最终会得到过时的数据。 #1可能已过时,因为添加/删除的原始保存可能尚未传播。因此查询会错过新记录。当您快速连续添加或移除多个项目时,#2将会有过时的数据。总数更新为保存1但保存2,保存1可能仍在传播,对于保存2的ShoppingList总计查询仍将反映保存前的原始状态1.
所以我的问题是,什么是正确的方法来解决这个问题对我来说,似乎你有两种选择:
- 使用缓存总数时总是使用memcached实体。保存不会清除内存缓存,而是直接将更新后的实体注入到内存中。这使memcache保持最新状态。这当然意味着不会触及memcache的查询(例如获取所有ShoppingList实体的列表)可能仍会返回陈旧的数据。但至少当所有的保存完成后,数据库中的缓存总数将是正确的。
- 处理您将要陈旧的数据,然后找出将来某个时间清理它的方法。可以安排一个TaskQueue重新查询ShoppingList并在10-30秒内更新总数或者计划一个每30秒运行一次的Cron Job并查找所有已更新的ShoppingList实体。
我倾向于解决方案#1。思考?
感谢您的建议。不幸的是我不能使用实体组,因为每秒写入限制为1。从文档:“这种方法通过写入每个留言簿的单个实体组来实现强大的一致性,但它也将留言簿的更改限制为每秒不超过1次写入(支持的实体组限制)” – dirkoneill 2014-11-12 00:25:08