Вопрос

Я пробую Google App Engine Java, однако отсутствие уникального ограничения усложняет задачу.Я был там через этот пост и этот блог предлагает метод реализации чего-то подобного.Мой опыт работы в MySQL. Переход в хранилище данных без уникального ограничения заставляет меня нервничать, потому что мне никогда раньше не приходилось беспокоиться о повторяющихся значениях, и проверка каждого значения перед вставкой нового значения все еще оставляет место для ошибки.

"Нет, вы по-прежнему не можете указать unique при создании схемы".

-- Дэвид Андерхилл рассказывает о GAE и уникальном ограничении (опубликовать ссылку)

Что вы, ребята, используете для реализации чего-то похожего на уникальный или первичный ключ?

Я слышал об абстрактном слое хранилища данных, созданном с использованием низкоуровневого API, который работал как обычная RDB, которая, однако, не была бесплатной (однако я не помню название программного обеспечения)

Схематический взгляд на мою проблему

sNo = biggest serial_number in the db
sNo++
Insert new entry with sNo as serial_number value //checkpoint
User adds data pertaining to current serial_number 
Update entry with data where serial_number is sNo 

Однако в строке № 3 (контрольная точка) я чувствую, что два пользователя могут добавить один и тот же sNo.И это то, что мешает мне работать с appengine.

Это было полезно?

Решение

Вы можете генерировать уникальные серийные номера для своих продуктов без необходимости применять уникальные идентификаторы или запрашивать весь набор объектов, чтобы выяснить, какой серийный номер в настоящее время является наибольшим.Вы можете использовать транзакции и одноэлементную сущность для генерации "следующего" серийного номера.Поскольку операция происходит внутри транзакции, вы можете быть уверены, что ни один из двух продуктов никогда не получит один и тот же серийный номер.

Однако такой подход может привести к ограничению производительности и масштабируемости вашего приложения.Если дело в том, что создание новых серийных номеров происходит не так часто, чтобы у вас возникали разногласия, это может сработать для вас.

Редактировать:Чтобы уточнить, синглтон, который содержит текущий - или следующий - серийный номер, который должен быть присвоен, полностью независим от любых объектов, которым на самом деле присвоены серийные номера.Не обязательно, чтобы все они были частью группы сущностей.У вас могут быть объекты из нескольких моделей, использующие один и тот же механизм для получения нового уникального серийного номера.

Я недостаточно хорошо помню Java, чтобы предоставить пример кода, и мой пример Python может показаться вам бессмысленным, но вот псевдокод, иллюстрирующий идею:

  1. Получите запрос на создание нового инвентарного товара.
  2. Введите транзакцию.
  3. Извлекает текущее значение отдельного объекта модели SerialNumber.
  4. Увеличьте значение и запишите его в базу данных
  5. Возвращайте значение при выходе из транзакции.

Теперь код, который выполняет всю работу по фактическому созданию складского товара и хранению его вместе с новым серийным номером, НЕ обязательно запускать в транзакции.

Предостережение:как я уже говорил выше, это может быть серьезным узким местом в производительности, поскольку в любой момент времени может быть создан только один серийный номер.Однако это дает вам уверенность в том, что серийный номер, который вы только что сгенерировали, уникален и не используется.

Другие советы

Это и другие подобные вопросы часто придумывают при разговоре о переходе от традиционного RDB к большому таковому описанию, как App Engine.

Часто полезно обсудить Зачем DataStore не поддерживает уникальные ключи, поскольку она информирует о мышлении, вы должны быть в том, чтобы думать о ваших схемах хранения данных. Причина уникальных ограничений недоступна, заключается в том, что она значительно ограничивает масштабируемость. Как вы сказали, принуждение ограничения означает проверку всех других объектов для этого свойства. Делаете ли вы это вручную в своем коде или в DataStore он делает автоматически за кулисами, он все еще должен произойти, а это означает более низкую производительность. Некоторые оптимизации могут быть сделаны, но это все равно должно происходить так или иначе.

Ответ на ваш вопрос - действительно подумать о том, почему вам нужно это уникальное ограничение.

Во-вторых, помните, что ключи делать существуют в хранилище данных, и являются отличным способом обеспечения простого уникального ограничения.

my_user = MyUser(key_name=users.get_current_user().email())
my_user.put()

Это гарантирует, что нет MyUser когда-либо снова создан с этим письмом, и вы также можете быстро получить MyUser С этим письмом:

my_user = MyUser.get(users.get_current_user().email())

В Runtime Python вы также можете сделать:

my_user = MyUser.get_or_create(key_name=users.get_current_user().email())

Который будет вставлять или получить пользователь с этим электронным письмом.

Все более сложное, чем это не будет масштабируемым, хотя. Так что действительно подумайте о том, нужна ли вам, что свойство, чтобы быть во всем мире уникальным, или если есть способы удаления необходимости этого уникального ограничения. Часто вы найдете с некоторыми небольшими обходными пусками, которые вам не понадобилось, что имущество будет уникальным в конце концов.

Я столкнулся с этой же проблемой в приложении, где пользователи должны были зарезервировать временное время. Мне нужно было «вставить» именно одну уникальную сущность TimeLot, ожидая пользователей одновременно запрашивать один и тот же время.

Я выделил пример того, как сделать это на приложении, а я Об этом. Отказ Размещение блога имеет примеры канонического кода с использованием DataStore, а также объективы. (Кстати, я бы посоветовал избежать JDO.)

Я также развернул живая демонстрация Где вы можете продвинуть двух пользователей на резервирование того же ресурса. В этой демонстрации вы можете испытать точное поведение App Engine Chickore нажмите кнопку.

Если вы ищете поведение уникального ограничения, они должны доказать полезные.

-брок

Сначала я подумал, что альтернативой методу транзакции в блоге broc могло бы стать создание одноэлементного класса, который содержит синхронизированный метод (скажем, addUserName(строковое имя)), отвечающий за добавление новой записи, только если она уникальна или генерирует исключение.Затем создайте contextlistener, который создает экземпляр единственного экземпляра этого синглтона, добавляя его в качестве атрибута к ServletContext.Затем сервлеты могут вызывать метод addUserName() для экземпляра singleton, который они получают через getServletContext .

Однако это НЕ очень хорошая идея, потому что GAE, скорее всего, разделит приложение на несколько JVM, поэтому все еще может возникнуть несколько экземпляров одноэлементного класса, по одному в каждой JVM. смотрите эту тему

Более GAE-подобной альтернативой было бы написать GAE-модуль, отвечающий за проверку уникальности и добавление новых элементов;затем используйте ручное или базовое масштабирование с помощью...

<max-instances>1</max-instances>

Затем у вас есть единственный экземпляр, запущенный в GAE, который действует как единая точка доступа, добавляя пользователей по одному в хранилище данных.Если вы обеспокоены тем, что этот экземпляр является узким местом, вы могли бы улучшить модуль, добавив организацию очередей или внутреннюю архитектуру master / slave.

Это модульное решение позволило бы добавлять множество уникальных имен пользователей в хранилище данных за короткий промежуток времени, без риска возникновения проблем с конфликтом entitygroup.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top