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

时间:2016-03-17 17:50:03

标签: python python-2.7 google-app-engine google-cloud-datastore

我有一个网站,最像博客,当我提交帖子时,它会立即将其放入数据库并更新缓存。看起来当缓存尝试更新自身时,db没有更新,并且我的缓存已经过时了,我有一个没有最后一篇文章的首页,我尝试了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('/')

2 个答案:

答案 0 :(得分:1)

请注意我对cachFront所做的更改以及对cachFront方法内post的调用,以便在未复制最终一致性的情况下手动添加条目。< / p>

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('/')

答案 1 :(得分:0)

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

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

您需要选择一个将成为所有实体的父级的实体,并在每次创建新的entrada时使用它:

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

在这种情况下,我建议您将第一篇文章作为默认父级,并抓住其密钥。所以你的代码将成为:

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('/')