Группа GAE / модель данных для согласованности и производительности

Как продолжение этой статьи, это немного вопрос в стиле capstone, чтобы укрепить мое понимание gae-datastore и получить некоторые критические замечания по моим решениям моделирования данных. Я буду модифицировать пример Jukebox, созданный @Jimmy Kane, чтобы лучше отразить мое дело в реальном мире.

В исходной настройке,


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

J=Jukebox, Q=queue, S=Song Jukebox / | \ Q1 Q2 Q3 / | \ | \ S1 S2 S3 S4 S5 

Во-первых, заполните модель песни как таковую:

 Song(ndb.Model): user_key = ndb.KeyProperty() status = ndb.StringProperty() datetime_added = ndb.DateTimeProperty() 

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

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

 User(ndb.Model): song_keys = ndb.KeyProperty(kind='Song', repeated=True) 

Затем, чтобы получить песни пользователя, приложение (предположим, что user_id известно)

 user = User.get_by_id(user_id) songs = ndb.get_multi(user.song_keys) 

И, поскольку get s сильно согласованы, пользователь всегда будет видеть не устаревшие данные

Затем, когда очередь 1 завершает воспроизведение песни, приложение может сделать что-то вроде:

 current_song.status = "inactive" current_song.put() query=Song.query(ancestor=ndb.Key('Jukebox', '1', 'Queue', '1')).filter(Song.status=="active").order(Song.datetime_added) next_song = query.get() 

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

Последним шагом было бы обновить список song_keys пользователя в транзакции

 user = current_song.user_key.get() user.song_keys.remove(current_song.key) user.put() 

Резюме и некоторые плюсы / минусы

  • Кажется, что согласованность делает правильные вещи в правильных местах, если мое понимание правильное?
  • Должен ли я беспокоиться о конкуренции в группе сущностей Jukebox ?
    • Я бы не ожидал, что это будет вариант с высокой пропускной способностью, но мой реальный сценарий должен масштабироваться с количеством пользователей, и, вероятно, есть аналогичное количество queue как есть user , возможно, в 2-5 раз больше user а не в queue . Если вся группа ограничена 1 записью / сек, и многие пользователи, а также каждая очередь могут создавать и обновлять песни, это может быть узким местом
    • Одним из решений может быть устранение корневой сущности Jukebox и каждая Queue это ее собственный корневой объект
  • User.song_keys может быть длинным, скажем, 100 song.key s. В этой статье рекомендуется избегать хранения слишком больших списков ключей в ListProperty. В чем проблема? Является ли это концепцией db и спорным способом обработки списков ndb с параметром repeat repeated=True ?

Мнения о таком подходе или критике в отношении вещей, которые я принципиально недопонимаю?

  • Предположительно, я мог бы также альтернативно, просто просто симметрично перевернуть модели данных и иметь группы сущностей, которые выглядят как User -> Song и хранить списки song_keys в модели Queue

2 Solutions collect form web for “Группа GAE / модель данных для согласованности и производительности”

Я думаю, вы должны пересмотреть, насколько важна сильная последовательность для вашего случая использования. Из того, что я вижу, не обязательно, что все эти сущности имеют сильную последовательность. На мой взгляд, конечная последовательность будет работать нормально. В большинстве случаев вы будете видеть последние данные и только иногда (читай: действительно очень редко) вы увидите некоторые устаревшие данные. Подумайте, насколько важно то, что вы всегда получаете последние данные, и насколько это наказывает ваше приложение. Объекты, которые нуждаются в сильной согласованности, не сохраняются наиболее эффективным способом с точки зрения количества чтений в секунду.

Также, если вы посмотрите на документ « Структурирование данных для сильной последовательности» , вы увидите, что в нем упоминается, что при использовании этого подхода вы не можете иметь более 1 записи в секунду.

Кроме того, наличие групп объектов влияет на местоположение данных в соответствии с документами класса AppEngine Model Class .

Если вы также прочтете знаменитый документ Google в Google Spanner , раздел 2, вы увидите, как они работают с объектами, которые имеют один и тот же родительский ключ. По существу, они сближаются. Я полагаю, Google может использовать аналогичный подход с AppEngine Datastore. В какой-то момент, согласно этому источнику, Google может использовать Spanner для AppEngine Datastore в будущем.

Еще один момент: дешевле быстрее получить, а затем получить ключ. Сказав это, если вы можете как-то избежать запроса, это может привести к снижению стоимости запуска вашего приложения. Предполагая, что вы разрабатываете веб-приложение, вы можете хранить ваши музыкальные клавиши в объекте JSON / text, а затем использовать API перспективного поиска для получения актуальных результатов. Этот подход требует немного больше работы и требует, чтобы вы приняли модель конечной согласованности, поскольку данные могут быть немного устаревшими к моменту, когда она достигает клиента. В зависимости от вашего варианта использования (это, очевидно, не применяется небольшое приложение и небольшая пользовательская база), экономия может привести к снижению стоимости. Когда я говорю о стоимости, я имею в виду тот факт, что данные могут быть немного устаревшими.

По моему опыту, сильная согласованность не является требованием для большого числа приложений. Количество приложений, которые могут жить с немного устаревшими данными, как представляется, превосходит число приложений, которые не могут. Возьмите YouTube, например, я не против, если я не сразу увижу все видео (так как есть такое большое количество, что я даже не знаю, вижу ли я их всех или нет). Когда вы создаете что-то вроде этого, сначала задайте себе вопрос, действительно ли необходимо предоставить обновленные данные или данные с немного устаревшим достаточно хороши? Может ли пользователь даже сказать разницу? Обновленные данные намного дороже, чем немного устаревшие.

Я решил использовать другой подход, который должен полагаться на списки song_keys в Queues в дополнение к пользователям. Таким образом, я имею сильную согласованность при работе с Пользователями и Очереди, не требуя решения компромисс производительности / согласованности, которое поставляется с группами сущностей. Как положительный побочный продукт, get ting keys использует ncb autocaching, поэтому я ожидаю повышения производительности с улучшенной простотой кода.

Все еще приветствуем любые критические замечания …

UDPATE: немного больше информации об автокашинге. NDB автоматически управляет кешированием через memcache и кеш в контексте. Для моих целей меня больше всего интересует автоматическая memcache. Используя преимущественно запросы на запросы в пользу запросов, NDB сначала проверит memcache перед чтением из хранилища данных для всех этих чтений. Я ожидаю, что большинство запросов действительно будет выполнено из memcache, а не в хранилище данных. Я понимаю, что я мог бы управлять всей этой деятельностью memcache самостоятельно и, скорее всего, таким образом, чтобы работать прилично с помощью подхода, ориентированного на запросы, поэтому, возможно, некоторые не считают это большим обоснованием для дизайнерского решения. Но влияние на простоту кода довольно приятно.

  • datetime.datetime.now () возвращает старое значение
  • Python Mechanize + код GAEpython
  • App Engine: структурированное свойство vs Ссылка для отношения «один ко многим»
  • Эффективно использовать Google App Engine для отправки большого количества писем с помощью PHP?
  • Можно ли запустить серверный javascript из экземпляра * Python * Google App Engine?
  • Запрос GQL Google App Engine на localhost
  • Вставка растрового изображения в файл Excel (xlwt) в GAE
  • Как использовать сеанс в Google приложении
  •  
    Interesting Posts for Van-Lav

    Автоматически сгенерированный код Python с диаграммы UML?

    Попен, ожидающий детского процесса, даже когда ближайший ребенок прекратил

    Как избежать «Разрешения отказа» при использовании pip с virtualenv

    чтение данных в tensorflow – TypeError («% s, которые не все совпадают».% prefix)

    Как использовать переменную в качестве индекса в шаблоне django?

    Python анализирует вывод текстового файла смешанного формата на ключевые слова пары слов

    1000 цифр pi в python

    Как создать объект datetime с помощью PyYAML

    Запустить код в скрипте python при выключенном сигнале

    Пикторизация вектора вложенных циклов

    повторное использование идентификатора объекта для других объектов разного типа – разумная идея?

    Pygame: Столкновение по сторонам

    Как преобразовать мой bytearray ('b \ x9e \ x18K \ x9a') в нечто подобное -> '\ x9e \ x18K \ x9a' <— просто str, а не массив

    Эффективное вычисление дисперсии изображения python

    Как реализовать простую кнопку в PyQt

    Python - лучший язык программирования в мире.