Фон ::::
Я работаю с Google App Engine (GAE) для Java.Я изо всех сил пытаюсь разработать модель данных, которая бы соответствовала сильным и слабым сторонам большого стола. Это два предыдущих связанных поста:
Я предварительно определился с полностью нормализованной магистралью с денормализованными свойствами, добавленными в сущности, чтобы большинство клиентских запросов можно было обслуживать только одним запросом.
Я полагаю, что полностью нормализованная магистраль будет:
- Помочь сохранить целостность данных, если я кодирую ошибку в денормализации
- Включить запись в одной операции от клиентаракурс
- Разрешить любой непредвиденный запрос к данным (при условии, что он готов ждать)
Пока денормализованные данные будут:
- Включитьбольшинство запросов клиентов обслуживаются очень быстро
Базовая техника денормализации :::
Я смотрел видео движка приложения, описывающее технику, называемую "разветвлением".Идея состоит в том, чтобы сделать быструю запись в нормализованные данные, а затем использовать очередь задач, чтобы завершить денормализацию за кулисами без необходимости ждать клиента.Я включил видео сюда для справки, но это час, и нет необходимости смотреть его, чтобы понять этот вопрос: http://code.google.com/events/io/2010/sessions/high-throughput-data-pipelines-appengine.html
Если я использую этот разветвительВ этом случае каждый раз, когда клиент изменяет некоторые данные, приложение обновляет нормализованную модель за одну быструю запись, а затем запускает инструкции по денормализации в очередь задач, чтобы клиенту не приходилось ждать, пока они завершатся.
Проблема :::
Проблема с использованием очереди задач для обновления денормализованной версии данных заключается в том, что клиент может сделать запрос на чтение данных, которые он только что изменил, до завершения очереди задачи.денормализация на этих данных.Это предоставит клиенту устаревшие данные, которые несовместимы с его недавним запросом, запутывающим клиента и заставляющим приложение казаться глючным.
В качестве исправления я предлагаю разложить операции денормализации параллельно через асинхронные вызовы других URL-адресовприложение через URLFetch: http://code.google.com/appengine/docs/java/urlfetch/ Приложение будет ожидать завершения всех асинхронных вызовов, прежде чем отвечать на запрос клиента.
Например, если у меня есть сущность «Назначение» и«Клиент» субъект.Каждое назначение будет включать в себя денормализованную копию информации о клиенте, для которого запланировано.Если бы клиент изменил свое имя, приложение сделало бы 30 асинхронных вызовов;по одному на каждый затронутый ресурс встречи, чтобы изменить копию имени клиента в каждом.
Теоретически, все это можно сделать параллельно.Вся эта информация может быть обновлена примерно за время, необходимое для выполнения 1 или 2 записей в хранилище данных.После завершения денормализации клиенту может быть предоставлен своевременный ответ, исключающий вероятность того, что клиент будет подвержен несоответствующим данным.
Самая большая потенциальная проблема, с которой я сталкиваюсь, заключается в том, что приложение не может иметь более 10вызовы асинхронных запросов, выполняемые в любое время (задокументировано здесь): http://code.google.com/appengine/docs/java/urlfetch/overview.html).
Предлагаемый метод денормализации (рекурсивное асинхронное разветвление) :::
Мое предлагаемое средство - отправлять инструкции по денормализации в другой ресурс, который рекурсивно разделяет инструкции на меньшие по размеру куски, вызывая себя с меньшими чанками в качестве параметров, пока количество инструкций в каждом чанке не станет достаточно маленьким для непосредственного выполнения. Например, если клиент с 30 связанными встречами изменил написание своего имени. Я бы назвал ресурс денормализации с инструкциями, чтобы обновить все 30 встреч. Затем он разделит эти инструкции на 10 наборов по 3 инструкции и сделает 10 асинхронных запросов к своему собственному URL с каждым набором из 3 инструкций. Как только набор инструкций станет меньше 10, ресурс будет сразу выполнять асинхронные запросы в соответствии с каждой инструкцией.
Мои проблемы с этим подходом:
- Это может быть истолковано как попытка обойти правила ядра приложения, что может вызвать проблемы. (URL-адрес даже не разрешается вызывать сам, поэтому на самом деле мне нужно иметь два URL-ресурса, которые обрабатывают рекурсию, которая будет вызывать друг друга)
- Это сложно с несколькими точками потенциального отказа.
Я бы очень признателен за этот подход.