Java GAE跨多个实例的强一致性异常

Java GAE跨多个实例的强一致性异常,java,entity-framework,google-app-engine,consistency,eventual-consistency,Java,Entity Framework,Google App Engine,Consistency,Eventual Consistency,我正在使用GAESDK1.8.9和Java1.7(Build45)。对于数据存储,我使用Datanucleus JDO v2。我已经将代码部署到生产环境中,为每个新的“订单”请求更新计数器,并且出现了一些一致性问题,我认为这些问题与在几秒钟内处理来自不同服务器的请求有关。数据存储实体由一个唯一的键(由我的应用程序生成)、几个日期字段和一个orderId计数器组成。数据存储中只有少数实体 这是我的逻辑的一个子集 keyId是StoreWrapper类中String类型的实例变量 StoreWrap

我正在使用GAESDK1.8.9和Java1.7(Build45)。对于数据存储,我使用Datanucleus JDO v2。我已经将代码部署到生产环境中,为每个新的“订单”请求更新计数器,并且出现了一些一致性问题,我认为这些问题与在几秒钟内处理来自不同服务器的请求有关。数据存储实体由一个唯一的键(由我的应用程序生成)、几个日期字段和一个orderId计数器组成。数据存储中只有少数实体

这是我的逻辑的一个子集

keyId是StoreWrapper类中String类型的实例变量

StoreWrapper类中的newOrderId()方法应在数据存储中获取所需的存储实体(基于keyId),增加实体的orderId值,使用更新后的值将实体更新回数据存储,最后将更新后的值(如果发生错误,则为0)返回给调用方。获取、递增和更新都发生在JDO事务中,使用事务的.begin()和.commit()方法

Store类中的newOrderId()方法只是增加orderId值(加上一些逻辑,以允许它在达到上限时滚动)

public int newOrderId(){ int orderId=0

PersistenceManager pm = PMF.get().getPersistenceManager();
Transaction tx = pm.currentTransaction();

Store tempStore = null;
try {
    tx.begin(); // Use a transaction to modify value (read, update, write)
    tempStore = pm.getObjectById(Store.class, keyId);
    tempStore.newOrderId();
    pm.makePersistent(tempStore); // Problem occurs regardless if this statement exists or not
    tx.commit();
    orderId = tempStore.getOrderId();
} catch (JDOObjectNotFoundException e) {
    // Do new store stuff
    ...
} catch (JDOUserException e) {
    System.out.println(e.getMessage());
} catch (JDODataStoreException e) {
    System.out.println(e.getMessage());
} catch (JDOCanRetryException e) {
    System.out.println(e.getMessage());
} catch (JDOOptimisticVerificationException e) {
    System.out.println(e.getMessage());
} catch (JDOFatalException e) {
    System.out.println(e.getMessage());
} catch (JDOException e) {
    System.out.println(e.getMessage());
} catch (Exception e) {
    System.out.println(e.getMessage());
} finally {
    if (tx.isActive())
        tx.rollback();
    pm.close();
}

return orderId;
}


当我在短时间内提交多个订单请求时,我注意到订单的另一个数据存储中存在重复的订单号。我的研究得出结论,当多个实例处理请求时,就会发生这种情况。在日志中,我可以看到每次发生这种情况时,重复的实例都是不同的。我的理解是,实体组默认为根(鉴于实体的简单性质,这种情况下就是这种情况,因为我在生成键时没有指定父级),但我无法清楚地理解为什么行为表现为“最终一致性”而不是“强一致性”。我已经为各种异常设置了几个捕获,但没有发现任何证据表明日志中出现了这些异常。我甚至将threadsafe设置为“false”,这样每个实例只处理一个请求,并且仍然会发生。是否必须设置一些设置来在多个实例之间强制执行“强一致性”?

当您说“简单地增加orderId值”时,您的意思是什么?该值存储在何处?如果orderid未在数据存储或memcache之类的服务中持久化,则为请求提供服务的每个实例(实例内存中)将独立地递增该值,并将导致具有相同orderid的多个实体。请记住,每个请求都可以由完全独立的实例提供服务,唯一共享的是memcache和数据存储(或者准确地说是GCS之类的其他共享服务)。Store类表示数据存储实体,并包含orderId整数和一个方法newOrderId(),以对其进行递增。StoreWrapper类中的方法newOrderId()(同名)通过getObjectById()获取数据存储实体,然后调用store.newOrderId()方法对其进行增量处理,所有操作都在事务中进行。这应该将orderId的更改保留到数据存储中,我的理解是,如果另一个实例同时执行相同的操作,其中一个实例将失败并抛出异常,因为使用事务强制执行“强一致性”策略。