Задержка чтения в хранилище данных App Engine после put()

Я пишу код для блога/новостного сайта. На главной странице есть 10 последних статей, а также есть раздел архива со всеми статьями, отсортированными по времени изменения по убыванию. В разделе архива я использую разбиение на страницы на основе курсоров и результаты кэширования I, начиная со второй страницы, поскольку страницы изменяются только при публикации новой статьи или существующих по какой-либо причине. На каждой странице 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(), и она работает так, как ожидалось. Может ли быть так, что прошло слишком мало времени после того, как я установил() обновление в хранилище данных и до того, как я получаю функциюArticlesPage() в функции cacheArchivePages()? Возможно, транзакция записи еще не закончилась, и поэтому я получаю старые результаты? Я попытался использовать time.sleep() и подождать несколько секунд, прежде чем вызывать cacheArchivePages(), и в этом случае я не смог воспроизвести это поведение, но мне кажется, что time.sleep() не очень хорошая идея. В любом случае мне нужно знать точную причину такого поведения и способы борьбы с ним.

Ответы

Ответ 1

Скорее всего, вы попадаете в "последовательные запросы". При использовании хранилища данных HR запросы могут использовать несколько старых данных, и для данных, написанных put(), должны быть видимыми запросы (нет такой задержки для get() по ключу или id). Задержка, как правило, измеряется в секундах, но я не думаю, что мы гарантируем верхнюю границу - если вы попадаете в неудачный сетевой раздел, может быть, часов, я думаю.

Есть все виды частичных решений: от обмана, когда автор последних записей просматривает результаты запроса на использование запросов предков (у которых есть своя доля ограничений). Вы можете просто предоставить кешу ограниченное время жизни и обновить его при чтении вместо записи.

Удачи!