мне нужно придумать стратегию для обработки клиентских-повторных попыток по созданию ввода данных-магазин:Идемпотентный клиент-retryable запись в AppEngine дается в конечном счете последовательные запросы и т.д.
- Клиент посылает запрос на создание нового запись в базе данных
- Сервер выполняет создание входа и готовит на успех Ответить
- некоторых ошибки случаются, что делает клиент считает, что запрос не был обработан (потеря пакетов, ...)
- клиента посылает такое же запрос на создание новая запись в базе данных снова
- сервер обнаруживает попытку и воссоздает и отправляет оригинальный ответ без создания другой записи данных магазина
- Клиент получает ответ
- Все счастливы и только одна запись была создана в базе данных
У меня есть одно ограничение: Сервер БЕСПЛАТНО! У клиента нет никакой информации о сеансе.
Моя текущая идея заключается в следующем:
- Tag каждый создать-запрос с гарантированным глобально уникальным идентификатором (вот как я создаю их, хотя они не слишком актуальны для вопроса):
- Используя хранилище данных (и memcache), я назначаю уникальный, монотонно увеличивающийся идентификатор для каждого экземпляра сервера после его загрузки (назовем его SI)
- Когда клиент запрашивает начальную страницу, экземпляр, который обслуживал запрос генерирует уникальную монотону nically увеличения загрузки страницы идентификатора (PL) и посылает SI.PL клиента вместе с содержимым страницы
- Для каждого создания-запроса, клиент генерирует уникальный запрос монотонно возрастающий идентификатор (RI) и отправляет SI.PL.RI вместе с запросом создать самые
- Для каждого создания-запроса, сервер сначала проверяет, знает ли она создать тег
- Если нет, то он создает новую запись и каким-то образом сохраняет тег создания, по с ним
- Если он знает тег, он использует его, чтобы найти первоначально созданную запись и воссоздает соответствующий ответ
Вот варианты осуществления, которые я имею в виду прямо сейчас, и их проблемы:
- Хранить создать тег как индексированные собственности внутри записи:
- Когда сервер получает запрос, он должен использовать запрос, чтобы найти любую существующую запись
- Проблемы: Поскольку запросы в AppEngine только в конечном счете, последовательным, он может пропустить запись
- Используйте создать тег как запись является ключевым:
- Должно быть нормально, как это гарантированно будет уникальным, если цифры не завернуть (вряд ли с долгот)
- Minor неудобством: Это увеличивает длину ключей записей, в любом впрок (ненужный накладные расходы)
- Основная проблема: Это будет генерировать последовательные ключи входа в хранилище данных, которые следует избегать любой ценой, как это creates hot-spots in the stored data и, таким образом, может повлиять на производительность значительно
Одно из решений я рассматриваю для варианта 2 является использование какого-то формула, которая принимает последовательные номера и повторно отображает их на уникальную, детерминированную, но случайный виде последовательности вместо для устранения горячих точек. Любые идеи о том, как могла выглядеть эта формула?
Или, может быть, есть лучший подход?
Кажется ужасно сложным. Должна быть некоторая комбинация данных (даже если это все), что делает ее уникальной (иначе вы не можете отличить повторную попытку), поэтому просто используйте эту комбинацию или хэш из нее в качестве вашего ключа. – Greg
@Greg Я могу использовать данные, это правда. Но, к сожалению, это не решает проблему согласованных запросов: запрос может по-прежнему возвращать пустой набор результатов, даже если запись уже существует. –
@Greg Возможно, я сделал звук более сложным, чем он есть. Достаточно тривиально делать id + = 1, чтобы генерировать эти «уникальные монотонно возрастающие» серверные, клиентские и, следовательно, запросы-идентификаторы. Это намного БОЛЕЕ быстрый и более переносимый, чем беспокоиться о том, какая часть данных мне нужна для хеша (то есть какая часть этого является уникальным идентификатором) и как обрабатывать потенциальные изменения в этой части данных другими клиентами до того, как будет получена повторная попытка. .. :) –