Денормализация в Google App Engine?

Фон::

Я работаю с 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 асинхронных запросов запросов, идущих в любой момент (задокументировано здесь): <а4 > ).

Предлагаемый метод денормализации (рекурсивный асинхронный разветвление):

Мое предлагаемое решение состоит в том, чтобы отправить инструкции денормализации другому ресурсу, который рекурсивно разделяет инструкции на меньшие куски меньшего размера, называя себя меньшими кусками в качестве параметров, пока количество инструкций в каждом блоке не будет достаточно маленьким, чтобы быть выполненным прямо. Например, если клиент с 30 связанными назначениями изменил орфографию своего имени. Я бы назвал ресурс денормализации инструкциями по обновлению всех 30 назначений. Затем он разделил бы эти инструкции на 10 наборов из 3-х инструкций и выполнил бы 10 асинхронных запросов на свой собственный URL-адрес с каждым набором из 3-х инструкций. Как только набор команд будет меньше 10, ресурс затем сделает асинхронные запросы в соответствии с каждой инструкцией.

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

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

Я бы очень признателен за вклад в этот подход.

Ответы

Ответ 1

Это звучит ужасно сложно, и чем сложнее дизайн, тем сложнее его кодировать и поддерживать.

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

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

Ответ 3

Я предлагаю вам легкое решение с Memcache. Обновление от вашего клиента, вы можете сохранить Entity в Memcache, сохраняя ключ обновленного Entity с обновлением статуса. Когда вы выполняете задачи, он удаляет статус Memcached. Затем вы должны проверить статус перед чтением, позволяя пользователю быть правильно информированным, если объект все еще "заблокирован".