GAE сильные аномалии согласованности в нескольких случаях
Я использую GAE SDK 1.8.9 с Java 1.7 (сборка 45). Для хранилища данных я использую Datanucleus JDO v2. Я развернул код в рабочей среде, чтобы обновить счетчик для каждого нового запроса "заказ", и у меня возникла пара проблем согласованности, которые, по моему мнению, связаны с обработкой запросов с разных серверов в течение нескольких секунд друг от друга. Сущность хранилища данных состоит из уникального ключа (сгенерированного моим приложением), пары полей даты и счетчика orderId. В хранилище данных есть только несколько таких объектов.
Вот подмножество моей логики...
keyId - это переменная экземпляра типа String в классе StoreWrapper
Метод newOrderId() в классе StoreWrapper должен извлечь нужную сущность Store (на основе keyId) в хранилище данных, увеличить значение orderId сущности, обновить сущность обратно в хранилище данных с обновленным значением и, наконец, вернуть обновленное значение (или 0, если произошла ошибка) для вызывающего абонента. Все выборки, приращения и обновления происходят в транзакции JDO с использованием методов.begin() и.commit() для транзакции.
Метод newOrderId() в классе Store просто увеличивает значение 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;
}
Когда я отправляю несколько запросов на размещение заказа в течение короткого периода, я замечаю дубликаты номеров заказов в другом хранилище данных для заказов. Мое исследование пришло к выводу, что это происходит, когда несколько экземпляров обрабатывают запросы. В журналах я вижу, что каждый раз, когда это происходит, экземпляр дубликатов отличается. Насколько я понимаю, группа сущностей по умолчанию имеет корень (что будет иметь место в данной ситуации, учитывая простую природу сущности, поскольку я не указываю родителя при генерации ключа), но нигде не могу найти ясного понимания относительно того, почему поведение действует как "возможная последовательность", а не "сильная последовательность". Я поместил несколько уловов для различных исключений, но не вижу доказательств того, что какие-либо из них встречаются в журналах. Я даже установил потокобезопасность на "ложь", поэтому для каждого экземпляра обрабатывается только один запрос, и он все еще происходит. Есть ли какие-то настройки, которые должны быть установлены для обеспечения "строгой согласованности" в нескольких экземплярах?