我如何在 Python 环境中获得 GAE 的强一致性

How do i get strongly consistency in GAE in Python enviroment

我有一个网站,最像博客,当我提交 post 它立即将其放入数据库并更新缓存。看起来当缓存尝试自我更新时,数据库没有更新,我得到了一个过时的缓存,我得到了一个没有最后一个 post 的首页,我试着把 time.sleep(1) ,然后它起作用了,但我想知道这是否必须与我没有为我的实体使用父级的情况有关,如果是的话我该怎么做?

def cachFront(update=False):
    key="top"
    entradas=memcache.get(key)
    if entradas is None or update:
        logging.error("DB QUERY")
        post= db.GqlQuery("select * from dbEntradas order by fecha_creacion desc limit 10")
        entradas=list(post)
        memcache.set(key, entradas)
    return entradas


class MainHandler(Handler):
    def get(self):
        entradas= cachFront()
        self.render("index.html", entradas=entradas)


class NewPostHandler(Handler):

    def renderizar(self, error="", titulo="", post=""):
        self.render("entradas.html", titulo=titulo, post=post, error=error)

    def get(self):
        self.render("entradas.html")

    def post(self):
        titulo= self.request.get("title")
        topic= self.request.get("topic")
        post= self.request.get("post")

        if titulo and post  and (topic!="Choose one.."):
            entrada= post_db.dbEntradas(title=titulo, post=post, topic=topic)
            entrada.put()
            time.sleep(1)// if i commet this line when i redirect i do not get a cache update intead i got the old page
            cachFront(True)
            self.redirect('/')

具体回答你的问题,是的,你可以使用父/祖先实体来解决你的问题。如果您希望对 dbEntradas 实体的写入永远不会超过 1 秒左右,那么这可能是一个很好的解决方案。

使用父实体告诉数据存储将所有共享祖先关系的实体保留在同一台服务器上(基本上不复制数据)。因此,您不必使用 time.sleep() 来写入您的实体,因为以下 GQL 调用将保证看到您之前放置的数据。

您需要选择一个实体作为所有实体的父实体,并在每次制作新的 entrada 时使用它:

post_db.dbEntradas(title=titulo, post=post, topic=topic, parent=post_parent)

在这种情况下,我建议将您的第一个 post 作为默认父级,并获取其密钥。所以你的代码会变成:

def post(self):
    titulo= self.request.get("title")
    topic= self.request.get("topic")
    post= self.request.get("post")

    if titulo and post  and (topic!="Choose one.."):
        parent_entrada = post_db.dbEntradas.query(post_db.dbEntradas.id == [[first_post_id_here]]).get()

        entrada= post_db.dbEntradas(title=titulo, post=post, topic=topic, parent = parent_entrada)
        entrada.put()
        cachFront(True)
        self.redirect('/')

请注意我对 cachFront 所做的更改以及对 post 方法中对 cachFront 的调用所做的更改,以便在最终一致性尚未复制的情况下手动添加您的条目.

def cachFront(update=False, prepend=None):
    key="top"
    entradas=memcache.get(key)
    if entradas is None or update:
        logging.error("DB QUERY")
        post= db.GqlQuery("select * from dbEntradas order by fecha_creacion desc limit 10")
        entradas=list(post)
        # manually prepend item to cache if it isn't available yet because
        # of eventual consistency
        if prepend and (not entradas or not entradas[0].key == prepend.key):
            entradas.insert(0, prepend)
            entradas = entradas[0:10]
        memcache.set(key, entradas)
    return entradas


class MainHandler(Handler):
    def get(self):
        entradas= cachFront()
        self.render("index.html", entradas=entradas)


class NewPostHandler(Handler):

    def renderizar(self, error="", titulo="", post=""):
        self.render("entradas.html", titulo=titulo, post=post, error=error)

    def get(self):
        self.render("entradas.html")

    def post(self):
        titulo= self.request.get("title")
        topic= self.request.get("topic")
        post= self.request.get("post")

        if titulo and post  and (topic!="Choose one.."):
            entrada= post_db.dbEntradas(title=titulo, post=post, topic=topic)
            entrada.put()
            cachFront(update=True, prepend=entrada)
            self.redirect('/')