Я немного разбирался в этом, и вот несколько комментариев, которыми можно поделиться.
Хотя я думал, что использование Mercurial от Python упростит задачу, но у DVCS есть множество функций, которые не нужны (особенно ветвление, слияние). Я думаю, что было бы проще просто украсть некоторые дизайнерские решения и внедрить базовую систему для моих нужд. Итак, вот что я придумала.
Blobs
Система создает json-представление записи, подлежащей архивированию, и генерирует ее хэш SHA-1 («идентификатор узла», если хотите). Этот хеш представляет состояние этой записи в данный момент времени и является таким же, как «blob» git.
1012 * Изменения *
Изменения сгруппированы в наборы изменений. Набор изменений принимает к сведению некоторые метаданные (временную метку, коммиттер и т. Д.) И ссылки на любые родительские наборы изменений и текущее «дерево».
Деревья
Вместо того, чтобы использовать подход Mercurial «Manifest», я выбрал «древовидную» структуру git. Дерево - это просто список BLOB-объектов (экземпляров модели) или других деревьев. На верхнем уровне каждая таблица базы данных получает свое собственное дерево. Следующим уровнем могут быть все записи. Если записей много (часто они есть), их можно разбить на поддеревья.
Это означает, что если вы измените только одну запись, вы можете оставить нетронутыми деревья в покое. Это также позволяет каждой записи иметь свой собственный BLOB-объект, что значительно упрощает управление.
Хранение
Мне нравится идея Revlog Mercurial, потому что она позволяет минимизировать хранение данных (сохраняя только наборы изменений) и в то же время обеспечивать быстрый поиск (все наборы находятся в одной структуре данных). Это делается для каждой записи.
Я думаю, что такая система, как MongoDB, была бы лучшей для хранения данных (это должно быть ключ-значение, и я думаю, что Redis слишком сосредоточен на хранении всего в памяти, что не важно для архива). Он будет хранить наборы изменений, деревья и журналы. Несколько дополнительных клавиш для текущего заголовка и т. Д., И система завершена.
Поскольку мы используем деревья, нам, вероятно, не нужно явно связывать внешние ключи с точным «блобом», на который он ссылается. Достаточно просто использовать первичный ключ. Я надеюсь!
Вариант использования: 1. Архивирование изменений
Как только изменение сделано, текущее состояние записи сериализуется в json, и для ее состояния генерируется хеш. Это сделано для всех других связанных изменений и упаковано в набор изменений. После завершения соответствующие журналы обновляются, новые деревья и поддеревья генерируются с новыми хешами объектов («blob»), а набор изменений «фиксируется» с метаинформацией.
Вариант использования 2. Восстановление старого состояния
После нахождения соответствующего набора изменений (поиск MongoDB?), Дерево затем перебирается, пока мы не найдем искомый идентификатор BLOB-объекта. Мы переходим в журнал изменений и получаем состояние записи или генерируем ее, используя доступные снимки и наборы изменений. Затем пользователь должен будет решить, нужно ли извлекать внешние ключи, но сделать это будет легко (используя тот же набор изменений, с которым мы начали).
Резюме
Ни одна из этих операций не должна быть слишком дорогой, и у нас есть эффективное для пространства описание всех изменений в базе данных. Архив хранится отдельно от рабочей базы данных, что позволяет ему делать свое дело и позволяет вносить изменения в схему базы данных с течением времени.