我已经使用App Engine几年了,似乎一次又一次出现HDR的问题就是当你在一个屏幕上更新数据时,你有时会检索到旧的数据。如果在更新的第二个或两个内进行只读请求,则该屏幕的只读版本。我知道这已被讨论过here和here。我知道问题是什么,但我想知道适当的解决方案是什么?这是我可以获得过时数据的示例。
假设您构建了一个购物清单应用。
Entity 1: ShoppingList
Entity 2: ShoppingListItem
ShoppingList实体上有一个字段,用于保存列表中的总项目数。第二个实体是您的ShoppingListItem。添加或删除ShoppingListItem时,需要更新ShoppingList上的总计。您有两种方法可以更新总数。
使用这两种解决方案,您最终都会得到过时的数据。 #1可能已过期,因为添加/删除的原始保存可能尚未传播。因此查询将错过新记录。当您快速连续添加或删除多个项目时,#2将具有过时数据。总计更新为保存1,但在保存2时,保存1可能仍在传播,保存2的ShoppingList总计查询仍将反映保存1之前的原始状态。
所以我的问题是,解决这个问题的正确方法是什么?对我来说,你似乎有两个选择:
我倾向于解决方案#1。想法?
答案 0 :(得分:4)
选项3是仔细阅读https://developers.google.com/appengine/docs/java/datastore/structuring_for_strong_consistency和https://developers.google.com/appengine/docs/java/datastore/structuring_for_strong_consistency。你遇到的是“最终一致性”的经典表现。特别注意实体组和祖先查询。
答案 1 :(得分:0)
我认为在大多数情况下@ david-w-smith的回答是正确的。但是,我在评论中提到他的答案,使用实体组存在很大的局限性。该限制是实体组每秒只能处理一次写入。对于只有少数用户的应用程序来说,这可能很好,但对于社交网络而言是不可接受的。
正如Google文档(https://developers.google.com/appengine/docs/java/datastore/structuring_for_strong_consistency)所建议的那样,我已经使用memcache实现了一个相当极端的缓存实现。所有shoppingList查询结果都存储在缓存中,当列表更新,添加或删除时,我还会更新缓存中查询结果的状态。我担心维护两个数据副本(数据库和内存缓存)的自然复杂性,但这就是UnitTests的用途。正确?