Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/google-app-engine/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python put()后应用程序引擎数据存储中的读取延迟_Python_Google App Engine_Google Cloud Datastore - Fatal编程技术网

Python put()后应用程序引擎数据存储中的读取延迟

Python put()后应用程序引擎数据存储中的读取延迟,python,google-app-engine,google-cloud-datastore,Python,Google App Engine,Google Cloud Datastore,我为博客/新闻网站编写代码。主页上有10篇最新的文章,还有一个归档部分,所有文章都按修改时间降序排列。在归档部分,我使用基于游标的分页,并缓存从第二页开始的结果,因为只有在新文章发布或现有文章出于某种原因进入草稿时,页面才会更改。每页有10篇文章。因此,当用户点击带有某个编号(不是第一个编号)的归档页面时,memcache会首先检查该页码结果。如果页面不存在,则会检查memcache中该页面的光标,然后使用该光标从数据存储中获取结果: class archivePage: def GET

我为博客/新闻网站编写代码。主页上有10篇最新的文章,还有一个归档部分,所有文章都按修改时间降序排列。在归档部分,我使用基于游标的分页,并缓存从第二页开始的结果,因为只有在新文章发布或现有文章出于某种原因进入草稿时,页面才会更改。每页有10篇文章。因此,当用户点击带有某个编号(不是第一个编号)的归档页面时,memcache会首先检查该页码结果。如果页面不存在,则会检查memcache中该页面的光标,然后使用该光标从数据存储中获取结果:

class archivePage:
    def GET(self, page):
        if not page:
            articles = memcache.get('archivePage')
            if not articles:
                articles = fetchArticles()
                memcache.set('archivePage', articles)
        else:
            if int(page) == 0 or int(page) == 1:
                raise web.seeother('/archive')
            articles = memcache.get('archivePage'+page)
            if not articles:
                pageCursor = memcache.get('ArchivePageMapping'+page)
                if not pageCursor:
                    pageMapping = ArchivePageMapping.query(ArchivePageMapping.page == int(page)).get()
                    pageCursor = pageMapping.cursor
                    memcache.set('ArchivePageMapping'+page, pageCursor)
                articles = fetchArticles(cursor=Cursor(urlsafe=pageCursor))
                memcache.set('archivePage'+page, articles)
每次创建新文章或更改现有文章的状态(草稿/已发布)时,我都会刷新存档页面结果和游标的缓存。我在将文章保存到数据存储后执行此操作:

class addArticlePage:     
    def POST(self):
        formData = web.input()
        if formData.title and formData.content:
            article = Article(title=formData.title,
                              content=formData.content,
                              status=int(formData.status))
            key = article.put()
            if int(formData.status) == 1:
                cacheArchivePages()
            raise web.seeother('/article/%s' % key.id())

def cacheArchivePages():
    articles, cursor, moreArticles = fetchArticlesPage()
    memcache.set('archivePage', articles)
    pageNumber=2
    while moreArticles:
        pageMapping = ArchivePageMapping.query(ArchivePageMapping.page == pageNumber).get()
        if pageMapping:
            pageMapping.cursor = cursor.urlsafe()
        else:
            pageMapping = ArchivePageMapping(page=pageNumber,
                                            cursor=cursor.urlsafe())
        pageMapping.put()
        memcache.set('ArchivePageMapping'+str(pageNumber), cursor.urlsafe())
        articles, cursor, moreArticles = fetchArticlesPage(cursor=cursor)
        memcache.set('archivePage'+str(pageNumber), articles)
        pageNumber+=1

问题来了。有时(没有规律,它是随机发生的)刷新缓存后,我会得到与刷新前相同的结果和归档页面的游标。例如,我添加了一篇新文章。它保存在数据存储中,并显示在首页和存档的第一页上(存档的第一页未缓存)。但其他存档页面不会更新。我已经测试了cacheArchivePages()函数,它可以正常工作。是不是在我对数据存储进行更新()之后,在cacheArchivePages()函数中获取ArticleSpage()之前,时间过得太少了?也许写事务还没有完成,所以我得到了旧的结果?我尝试使用time.sleep()并在调用cacheArchivePages()之前等待几秒钟,在这种情况下,我无法重现这种行为,但在我看来,time.sleep()不是一个好主意。不管怎样,我需要知道这种行为的确切原因以及如何处理。

你很可能会被“最终一致性查询”击中。使用HR数据存储时,查询可能会使用稍旧的数据,并且需要一段时间才能让查询看到由put()编写的数据(对于按键或id获取()不会有这种延迟)。延迟通常以秒为单位,但我认为我们不能保证一个上限——如果你被一个不幸的网络分区击中,我想可能需要几个小时

有各种各样的局部解决方案,从最近写的文章的作者在查看查询结果时作弊,到使用祖先查询(它们有自己的限制)。您可以简单地给缓存一个有限的生存期,并在读时而不是写时更新它


祝你好运

谢谢你,圭多!我应该更加注意数据的一致性,并牢记人力资源数据存储的特点。在这种情况下,我很容易比较旧结果和新结果,如果它们相同,就可以重新启动查询。我投了赞成票,因为“使用祖先查询”正是解决我应用中延迟问题的方法,谢谢你。