数据存储区 - 单个实体组中的资源争用 -

Posted

技术标签:

【中文标题】数据存储区 - 单个实体组中的资源争用 -【英文标题】:Datastore - Resource contention in a single entity group - 【发布时间】:2012-07-31 16:42:33 【问题描述】:

我对有关数据存储的以下内容感到迷茫:

建议对数据进行非规范化处理,因为 Datastore 不支持连接查询。这意味着在多个实体中复制相同的信息

非规范化意味着每当您必须更新 数据,必须在不同的实体中更新

但单个实体组有 1 次写入/秒的限制。

因此我遇到的问题如下:

为了更新记录,我打开了一个事务

更新所有必需的实体。要更新的实体在同一个实体组中,但涉及到不同的种类

我收到“资源争用”异常

==> 因此,更新非规范化数据的唯一方法似乎是在事务之外。但是这样做真的很糟糕,因为有些实体可以更新,而其他实体则不能。

只有我一个人有这个问题吗?你是怎么解决的?

谢谢,

雨果

(简化版)代码如下:

Objectify ofy=ObjectifyService.beginTransaction();

try 
  Key<Party> partyKey=new Key<Party>(realEstateKey, Party.class, partyDTO.getId());

  //--------------------------------------------------------------------------
  //-- 1 - We update the party
  //--------------------------------------------------------------------------
  Party party=ofy.get(partyKey);
  party.update(partyDTO);

 //---------------------------------------------------------------------------------------------
 //-- 2 - We update the kinds which have Party as embedded field, all in the same entity group
 //--------------------------------------------------------------------------------------------- 

  //2.1 Invoices

  Query<Invoice> q1=ofy.query(Invoice.class).ancestor(realEstateKey).filter("partyKey", partyKey);
    for (Invoice invoice: q1) 
      invoice.setParty(party);
     ofy.put(invoice);
   
  //2.2Payments 
  Query<Payment> q2=ofy.query(Payment.class).ancestor(realEstateKey).filter("partyKey", partyKey);
    for (Payment payment: q2) 
      payment.setParty(payment);
     ofy.put(payment);
   


  ofy.getTxn().commit();
  return (RPCResults.SUCCESS);


catch (Exception e)        
        final Logger log = Logger.getLogger(InternalServiceImpl.class.getName());       
        log.severe("Problem while updating party : " + e.getLocalizedMessage()); 
       return (RPCResults.FAILURE)  ;    


finally 
    if (ofy.getTxn().isActive()) 
      ofy.getTxn().rollback();
     partyDTO.setCreationResult(RPCResults.FAILURE);
    return (RPCResults.FAILURE) ;        
                  

【问题讨论】:

能否请您发布错误的代码和堆栈跟踪? @mjibson 堆栈跟踪:com.plugimmo.web.server.internal.service.InternalServiceImpl requestUpdateLease:更新租约时出现问题:这些数据存储实体的争用过多。请再试一次。 如果您发布您的代码,也许我们可以提供更多帮助。 @mjibson。对不起,忘了添加我刚刚做的代码。我不太明白你所说的 put_multi() 是什么意思。第二个选项(高流量站点)此时不正确。只有少数用户 【参考方案1】:

发生这种情况是因为在短时间内发生了多个更新同一实体组的请求,而不是因为您同时更新同一实体组中的多个实体。

由于您没有显示您的代码,我可以假设正在发生以下两种情况之一:

    您上面描述的方法实际上并没有使用事务,并且您正在使用同一实体组的许多实体运行put_multi()。 (如果非要我猜的话,就是这个。) 您有一个高流量的网站,并且同时发生了许多其他更新。

【讨论】:

对不起,我忘了添加我的代码。您会在下面找到简化版本: 感谢您的帮助。非常感谢,Hugues【参考方案2】:

以防万一有人遇到同样的问题。

问题出在 party.update(partyDTO) 中,在某些特定条件下,我正在启动另一笔交易。

我今天学到的是:

--> 在一个事务中,即使超过 1 个实体/秒,您也可以包含多个 put

--> 但是,您应该注意不要在您的事务中启动另一个事务

【讨论】:

以上是关于数据存储区 - 单个实体组中的资源争用 -的主要内容,如果未能解决你的问题,请参考以下文章

单个 NAT 网关可以跨多个 AZ 吗?

如何为 Laravel ORM 中每个组中的单个项目执行 groupBy()

查询单个表中每个组中的前 5 名候选人

GAE DataStore 如何支持事务?

实验4

死锁的理解