Как работать с ежедневными / еженедельными / ежемесячными досками в хранилище данных AppEngine? - PullRequest
2 голосов
/ 24 декабря 2010

Я разрабатываю высокопроизводительный веб-сервис для своей игры, и он работает на Google App Engine.

В моей игре 5 сложностей, поэтому у меня изначально было 5 досок с записями для каждой (player_login, счет и время). Если игрок предоставил более низкий балл, чем предыдущий, он был отклонен, поэтому для каждого игрока сохраняется только самый высокий балл.

Но чтобы добавить еще больше веселья, я решил включить ежедневные / еженедельные / ежемесячные / ежегодные таблицы рекордов. Итак, я создал 5 досок для каждой сложности, из которых 25 досок. Когда счет отправляется, он сохраняется на каждой доске, и доски должны очищаться каждый день / неделю / месяц / год.

Это происходит при выполнении задания cron, которое удаляет все записи с определенной доски.

Здесь возникает проблема: похоже, что удаление записей из хранилища данных происходит медленно. Из моих тестов ежедневной очистки похоже, что удаление одной записи занимает около 200 мс.

В худшем случае, если игра будет достаточно популярной и будет иметь, скажем, 100 000 игроков, и у каждого из них будет запись на ежегодной доске, это займет 100 000 * 0,012 секунды = 12 000 секунд (3 часа !!), чтобы очистить эту доску. Я думаю, что в App Engine нам разрешено работать до 30 секунд, поэтому это не сработает.

Я удаляю с следующий код (спасибо Нику Джонсону) :

q = Score.all(keys_only=True).filter('b = ',boardToClear)
results = q.fetch(500)
  while results:
    self.response.out.write("deleting one batch;")
    db.delete(results)
    q = Score.all(keys_only=True).filter('b = ',boardToClear).with_cursor(q.cursor())
    results = q.fetch(500)

Что вы посоветуете мне сделать с этой проблемой?

Один из подходов, который мне приходит в голову, состоит в том, чтобы использовать очередь задач и удалять более старые оценки, чем те, которые разрешены на каждой доске, то есть, которые истекли, но в меньших количествах. Таким образом, я бы не достиг предела ЦП для одной задачи, но очистка не будет (почти) мгновенной, поэтому моя очистка длиной 12 000 секунд будет разделена на 1 200 задач, каждая примерно по 10 секунд.

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

Ответы [ 2 ]

4 голосов
/ 24 декабря 2010

Во-первых, пара небольших предложений:

  1. Требуется ли удаление 200 мс на элемент, даже если вы удаляете элементы в пакетном процессе?Самый быстрый способ удаления должен сделать запрос keys_only, а затем вызвать db.delete() сразу для всего списка ключей.
  2. Недавно 30-секундное ограничение было уменьшено до 10 минут для фоновой работы (как задачи cron или задачи очереди, которые вы рассматриваете) с 1.4.0 .

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

  1. Как вы предлагаете, используйте очередь задач для разделениядолгосрочные задачи в несколько небольших задач.Ваш вариант использования (удаление огромного количества элементов, соответствующих определенному запросу) идеально подходит для задачи сокращения карты.Сообщение Ника Джонсона о Mapper API может быть очень полезным для вас (чтобы вам не приходилось самостоятельно писать весь этот код управления задачами).
  2. Вам нужно?немедленно удалить все устаревшие записи на доске?Если у вас есть поле, в котором указана неделя, месяц или год, на который рассчитывает конкретная запись, вы можете индексировать это поле, а затем отображать только записи текущего месяца в видимой таблице лидеров.(В конце концов, дисковое пространство дешевое.) А затем, если вы хотите медленно (скажем, в течение нескольких часов, а не миллисекунд) удалять устаревшие данные, вы можете сделать это в фоновом режиме, не имея неверных данныхсписки лидеров.
3 голосов
/ 24 декабря 2010

Удалить объекты в пакетах. Хотя одно удаление занимает заметное количество времени (хотя 200 мс кажется очень высоким), пакетное удаление больше не занимает, так как они удаляют все объекты параллельно. Задания очереди задач и cron теперь могут выполняться до 10 минут, поэтому время ожидания не должно быть проблемой.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...