В Google App Engine, как я могу обеспечить конечную согласованность при обработке отправленных форм?

Я заметил, что при возможной согласованности обычный рабочий процесс обработки форм, к которому я привык (отправить -> создать/обновить запись -> перенаправить -> перезагрузить), не работает. При перенаправлении новая запись (вероятно) не будет доступна для отображения. Как мне обрабатывать формы, чтобы обновления отображались при перезагрузке?

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

Итак, как я могу обработать форму, обеспечивающую немедленную обратную связь с пользователем с согласованностью в конечном итоге?




Ответы (2)


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

У меня есть панель управления пользователя, где пользователь может создавать и удалять «элементы». Мои сущности выглядели так:

class User(ndb.Model)
    ...

class Item(ndb.Model)
    user = ndb.KeyProperty(User, required=True)

Раньше я делал такой запрос при ответе на запрос GET для пользовательской панели.

items = Item.query(user=user.key)

Это был плохой опыт, потому что пользователь удалял элемент, и после POST/redirect/GET только что удаленный элемент снова появлялся на панели инструментов из-за возможной согласованности.

Чтобы исправить это, я изменил свою сущность пользователя, чтобы иметь список элементов, подобных этому:

class User(ndb.Model)
    items = ndb.KeyProperty(repeated=True)
    ...

Теперь, когда я показываю панель инструментов, я делаю это:

items = ndb.get_multi(user.items)

Так как я сейчас получаю по ключу, данные всегда актуальны.

Это работает для меня, потому что у пользователя не будет так много элементов. Однако если бы пользователь мог иметь тысячи элементов, этот подход не работал бы из-за ограничения размера объекта.

person gaefan    schedule 15.01.2016
comment
Спасибо за Ваш ответ. Это не совсем отвечает на мой вопрос, который больше сосредоточен на случае, который может превышать предельный размер объекта. Тем не менее, ваш пример помогает мне понять, как строгая согласованность может применяться более широко, чем я изначально предполагал. - person klenwell; 16.01.2016

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

Это связано с тем, что базовый протокол согласованности Google без мастера (Paxos) гарантирует строгую согласованность только при работе в группе объектов (определяемой как целая группа ключей под корневым ключом и включая этот корневой ключ, где возможный родитель всех некорневых keys — это корневой ключ — см. Транзакции и группы сущностей чтобы узнать больше).

Цитата из руководства:

Как упоминалось выше, группа объектов – это набор объектов, связанных родословной с общим корневым элементом. Организация данных в группы сущностей может ограничить количество выполняемых транзакций:

... [подробности о транзакциях] ...

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

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

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

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

Дополнительную информацию см. в разделе Структурирование для строгой согласованности.

person sgammon    schedule 15.01.2016
comment
Благодарим за уточнение ограничения на одну транзакцию в секунду в рамках одной группы объектов. Это важно и делает сильную согласованность более широко применимой. Тем не менее меня интересует случай, когда модель не может быть структурирована для строгой согласованности. Я добавлю пояснение к моему вопросу и попытаюсь предоставить конкретный вариант использования. Тем не менее, я ценю ваш ответ. - person klenwell; 16.01.2016