代码之家  ›  专栏  ›  技术社区  ›  subcoder

Ndb强一致性和频繁写入

  •  0
  • subcoder  · 技术社区  · 7 年前

    我试图使用python实现与ndb的强一致性。 看起来我遗漏了一些东西,因为我的读数表现得不太一致。

    查询是:

    links = Link.query(ancestor=lead_key).filter(Link.last_status == 
    None).fetch(keys_only=True)
    
    if links: 
        do_action() 
    

    关键结构是:

    Lead root (generic key) -> Lead -> Website (one per lead) -> Link
    

    我有许多任务是使用TaskQueue并发执行的,这个查询是在每个任务结束时执行的。有时在更新 last_status

    do_action() 在没有剩余链接时调用 上次_状态 None do_action() 被调用两次,有时根本不调用。

    3 回复  |  直到 7 年前
        1
  •  1
  •   Dave W. Smith    7 年前

    使用祖先密钥来获得强一致性有一个限制:每个实体组每秒只能更新一次。解决这个问题的一种方法是分割实体组。 Sharding Counters 描述了该技术。这是一篇旧文章,但据我所知,建议仍然很合理。

        2
  •  1
  •   Dan Cornilescu    7 年前

    再加上Dave的答案,这是要检查的第一件事。

    有一件事没有很好的文档记录并且可能有点令人惊讶,那就是争用也可能是由读取操作引起的,而不仅仅是由写入操作引起的。

    每当事务开始时,被访问的实体组(通过读或写操作,无关紧要)都被标记为这样。这个 too much contention

    注: 这一论点是 不是

    增加混乱的是事务的自动重试,这可能发生在实际写入冲突或纯访问争用之后。在最终用户看来,这些重试可能是某些代码路径的可疑重复执行,我怀疑这可以解释您的报告 do_action() 被叫了两次。

        3
  •  0
  •   gregdarke    7 年前

    示例中没有任何内容可以确保代码只被调用一次。

    请记住,即使您确实使用了事务,在事务成功完成之前,您也不知道其他人是否尝试执行写操作。如果您试图在数据存储外部执行某些操作(例如,向外部系统发出http请求),这一点很重要,因为您可能会看到来自事务的http请求最终会因并发修改异常而失败。