Как вы управляете значительным изменением схемы, когда используете хранилище Nosql, такое как SimpleDB?

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

С базой данных SQL вы должны запустить набор операторов sql как часть процесса развертывания клиентского программного обеспечения. Очевидно, что это не будет работать с чем-то вроде SimpleDB, поскольку

  • нет эквивалента инструкции обновления SQL.
  • Из-за распределенной природы SimpleDB невозможно узнать, когда изменения, внесенные в базу данных, «отфильтрованы» на все узлы, на которых работает ваше клиентское программное обеспечение.

Некоторые решения, о которых я подумал,

  • У каждого домена есть номер версии. Клиентское программное обеспечение знает, какую версию домена следует использовать. Напишите код, который копирует данные из одной версии домена в другую, внося необходимые изменения по ходу дела. Затем вы можете установить новое клиентское программное обеспечение, которое затем получит доступ к новой версии домена. Этот подход не будет работать, если вы не сможете «заморозить» весь доступ для записи во время процесса обновления.

  • У каждого элемента есть атрибут версии, который указывает формат, использованный при его сохранении. Клиент использует этот атрибут при загрузке объекта в память. Затем объект можно преобразовать в последний формат, когда он будет записан обратно в SimpleDB. Проблема заключается в том, что новое программное обеспечение необходимо развернуть на всех серверах до того, как произойдет какая-либо запись в новом формате, иначе клиенты, работающие со старым программным обеспечением, не будут знать, как читать новый формат.

Все это довольно сложно, и мне интересно, не упускаю ли я чего-то?

Благодарность

Ричард

9
richard 30 Авг 2011 в 09:42

2 ответа

Лучший ответ

Я использую что-то похожее на ваш второй вариант, но без атрибута версии.

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

Удалить поле очень просто - просто прекратите писать в это поле, как только на всех серверах будет запущена версия, которая этого не требует.

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

Изменение поля - это просто комбинация этих двух операций.

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

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

С изменением первичного ключа можно справиться таким же образом, но это может быть очень сложным в зависимости от того, какую систему nosql вы используете. В этом случае вы, вероятно, застряли в разработке пользовательского кода миграции.

5
Tom Clarkson 31 Авг 2011 в 00:39

RavenDB, другая база данных NoSQL, использует миграции для достижения этой цели.

http://ayende.com/blog/66563/ravendb-migrations-rolling-updates

http://ayende.com/blog/66562/ravendb-migrations-when-to-execute

Обычно такие изменения обрабатываются вашим приложением, которое меняет схему на более новую при загрузке версии X и преобразовании в версию Y и сохранении.

1
Justin King 30 Авг 2011 в 05:46