我正在使用GAE SDK 1.8.9和Java 1.7(build 45)。对于数据存储区,我使用的是Datanucleus JDO v2。我已经将代码部署到生产中以更新每个新订单的计数器" order"请求并且我遇到了一些一致性问题,我认为这些问题与在几秒钟内处理来自不同服务器的请求有关。数据存储区实体由唯一键(由我的应用程序生成),几个日期字段和orderId计数器组成。数据存储区中只有少数这些实体。
这是我逻辑的一个子集......
keyId是StoreWrapper类
中String类型的实例变量StoreWrapper类中的newOrderId()方法应该获取数据存储区中所需的Store实体(基于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;
}
当我提交多个请求以在短时间内下订单时,我注意到订单中另一个数据存储区中的重复订单号。我的研究得出结论,当多个实例处理请求时会发生这种情况。在日志中,我可以看到每次发生这种情况时,重复项的实例都不同。我的理解是,实体组默认为根(考虑到实体的简单性,这种情况就是这种情况,因为我在生成密钥时没有指定父级),但我无处可寻找清楚地理解为什么行为表现得像"最终的一致性"而不是强烈的一致性"。我已经针对各种异常放置了几个捕获,但是没有看到任何证据表明这些异常发生在日志中。我甚至将线程安全设置为“假”'因此每个实例只处理一个请求,但仍然会发生。是否有一些设置必须设置为强制执行"强一致性"跨多个实例?