Поток rdiff - дельта-дифференциация?

У меня есть продукт, который делает онлайн-бэкапы с помощью rdiff. В настоящее время происходит следующее:

  1. Скопируйте файл в промежуточную область (чтобы файл не исчез или не изменился, пока мы работаем над ним)

  2. Хэширует исходный файл и вычисляет сигнатуру rdiff (используется для дельта-дифференциации) Вычисляет дельта-разницу rdiff (если у нас нет предыдущей версии, этот шаг пропускается)

  3. Сжимает и шифрует полученную дельта-разность

В настоящее время эти этапы выполняются отдельно друг от друга. Конечным результатом является то, что мы перебираем файл несколько раз. Для небольших файлов это не имеет большого значения (особенно с учетом кэширования диска), но для больших файлов (10 или даже 100 ГБ) это настоящий убийца производительности.

Я хочу объединить все эти шаги в один проход чтения/записи.

Для этого мы должны иметь возможность выполнять все вышеперечисленные шаги в потоковом режиме, сохраняя при этом все «выходные данные» — хэш файла, подпись rdiff, сжатый и зашифрованный файл дельта-разницы. Это повлечет за собой чтение блока данных из исходного файла (скажем, 100 КБ?), Затем перебор файла в памяти для обновления хэша, подписи rdiff, дельта-дифференциации, а затем запись вывода в выходной поток сжатия/шифрования. . Цель состоит в том, чтобы значительно свести к минимуму количество перегрузок диска, которые мы делаем.

В настоящее время мы используем rdiff.exe (который представляет собой тонкий слой поверх базовой библиотеки librsync) для вычисления подписей и создания двоичных дельт. Это означает, что они выполняются в отдельном процессе и выполняются за один раз, а не в потоковом режиме.

Как я могу заставить это делать то, что мне нужно, используя библиотеку librsync?


person spentak    schedule 16.02.2011    source источник


Ответы (1)


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

Вам необходимо вычислить всю подпись rdiff, прежде чем вы сможете начать создавать дельту rdiff. Вы можете избежать чтения всего файла, вычисляя подписи, а затем дельты для каждого (скажем) 100-мегабайтного блока файла за раз. Таким образом вы немного потеряете эффективность сжатия*. Вы также можете подумать о переходе с rdiff на xdelta, который может создать дельта-файл за один проход по входным данным.

Сжатие и шифрование можно выполнять параллельно с вычислением дельты. Если сжатие и шифрование выполняются отдельными программами, они часто позволяют читать из стандартного ввода и записывать в стандартный вывод. Проще всего это можно использовать с помощью каналов в пакетном файле, например:

rdiff signature oldfile oldfile.sig
rdiff delta oldfile.sig newfile | gzip -c | gpg -e -r ... > compressed_encrypted_delta

Если вы используете в своей программе библиотеки для сжатия/шифрования, вам нужно будет выбрать библиотеки, поддерживающие потоковую работу.

* или потерять большую эффективность, если данные перемещаются в файле. Если кто-то добавит 100 МБ к файлу размером 10 ГБ, rdiff создаст дельта-файл размером около 100 МБ. rdiff, выполняемый блоками по 100 МБ или меньше за раз, даст около 10 ГБ дельты. Блоки по 200 МБ дадут около 5 ГБ дельты, так как только половина данных в каждом блоке — из соответствующего блока старой версии файла.

person Baffe Boyois    schedule 16.02.2011
comment
Что вы имеете в виду, соответствующие флаги блокировки? Как мне это сделать? Кроме того, вы сказали, что сжатие и шифрование могут выполняться параллельно с вычислением дельты, как это достигается? Я просто не понимаю (после нескольких часов попыток реализовать это), как это возможно. Чтобы ты делал? - person spentak; 17.02.2011