Таблица поиска GAE несовместима с транзакциями? - PullRequest
0 голосов
/ 17 сентября 2011

Моему приложению Python High Replication Datastore требуется большая таблица поиска от 100 000 до 1 000 000 записей. Мне нужно иметь возможность предоставить код некоторому методу, который будет возвращать значение, связанное с этим кодом (или None, если нет связи). Например, если моя таблица содержит приемлемые английские слова, я бы хотел, чтобы функция возвращала True, если слово было найдено, и False (или None) в противном случае.

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

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

Обратите внимание, что моя таблица поиска исправлена ​​или изменяется очень редко. Опять же, это соответствует примеру проверки орфографии.

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

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

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

Кто-нибудь знает подходящую реализацию для больших глобальных таблиц поиска?

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

Ответы [ 2 ]

1 голос
/ 19 сентября 2011

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

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

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

Если ваши данные обязательно должны быть в хранилище данных, вам может потребоваться эмулировать ваши собственные транзакции чтения-изменения-записи.Добавьте свойство 'revision' в свои записи.Чтобы изменить его, извлеките запись (вне транзакции), внесите необходимые изменения, затем внутри транзакции извлеките ее снова, чтобы проверить значение ревизии.Если он не изменился, увеличьте редакцию в своей собственной записи и сохраните ее в хранилище данных.

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

Один последний вариант: вы можете запустить бэкэнд, предоставляющий больше памяти, обнажая'SpellCheckService' и выполняйте вызовы URLFetch на него из своих веб-интерфейсов.Помните, что оперативная память всегда будет намного, намного быстрее, чем любая дисковая опция.

1 голос
/ 17 сентября 2011

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

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

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

...