【问题标题】:Threadsafe name reservation on appengineappengine 上的线程安全名称保留
【发布时间】:2011-03-11 17:39:58
【问题描述】:

我正在创建和编辑组。在使用该名称创建新组或将现有组名称更改为该名称之前,我需要检查组名称是否已在使用中。

问题是两个并行线程可以同时检查组名,然后每个线程可以继续添加自己的组。重复的名字!

我认为我不能使用内置事务,因为这些组应该位于不同的实体组中,并且名称不是键的一部分。我能做什么?

创建一种在键中使用组名的索引实体是否有意义,以便我可以执行祖先查询以原子方式获取和创建名称?创建索引实体的成功将作为非事务性代码执行的许可。我希望有一个更简单的解决方案,不需要全新类型的实体。

【问题讨论】:

    标签: google-app-engine transactions thread-safety google-cloud-datastore


    【解决方案1】:

    您所描述的“索引实体”是一种标准方法,尽管我不知道您对使用祖先查询的意思是什么 - 索引实体既不应该是任何其他实体的子实体,也不应该有任何子实体.

    请记住这样做的事务影响:意外失败可能导致名称被保留但未使用。

    【讨论】:

      【解决方案2】:

      您能否使用Memcache 解决方案而不是新实体?您可能需要定期清除它。

      【讨论】:

        【解决方案3】:

        有没有办法使用组名(或基于名称的哈希)作为键?因为那个 + group.get_or_insert(group_name) 基本上可以解决你的问题。该方法自动在事务中运行,并使用该 key_name 创建或检索实体。

        【讨论】:

        • 我非常习惯使用Long ids 来引用客户端的实体。当然,切换是一种选择,并且可能比我的索引实体解决方案更容易(并且更能抵抗错误)。感谢您的提示。
        • @Riley hashlib.sha256('my group name').hexdigest()hashlib.sha256('my group name').digest().encode('base64') 将为您提供可用作键的哈希值,并可在客户端使用(尽管它们会使您的 URL 变得丑陋)。
        • 更好:base64.urlsafe_b64encode(hashlib.sha256('my group name').digest()).rstrip('=')
        【解决方案4】:

        你们真的认为事务可以用作线程锁吗?没有。

        此外,在并行计算环境下避免竞争条件的最佳方法是避免写入冲突。也就是说,修改您的结构,延迟并将组名写入收集到单个线程中。是的,它不是实时的,但我怀疑你是否真的需要实时组名生成。请记住,如果您想要的不仅仅是一个玩具系统,请在任何地方使用异步并拥抱不一致性。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-03-28
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多