Предыстория
При проектировании программного обеспечения порой возникают неожиданные вопросы. Мой коллега задал один такой вопрос, когда решал, как устроить работу с файлами в веб-приложении. Методы взаимодействия с файлами давно отработаны, и существуют две основные стратегии: хранить файлы прямо в базе данных или записывать в базу данных только ссылки, а сам файл оставить в файловой системе сервера.
Коллега решил рассмотреть третий вариант (который впоследствии был аргументированно отвергнут). Один и тот же файл по логике приложения нужно использовать в нескольких местах (во многих местах), для этого он предложил просто задавать имя по шаблону, а для множественного использования создавать ссылки (символьные или жёсткие в файловой системе, не веб ссылки типа a href=…).
Символьные ссылки знакомы большинству разработчиков и системных администраторов и не вызывают вопросов. Однако hard link — вещь менее очевидная, особенно для разработчиков на скриптовых языках (PHP, JavaScript, Python). Желая заполнить этот пробел, я и пишу эту статью. Рассматривать буду на примере Windows, т. к. пользователи Linux, как правило, лучше разбираются в этой теме, по крайней мере иногда сталкиваются. А вот Windows разработчики (всё на тех же скриптовых языках) и системные администраторы могут десятилетиями успешно работать, не касаясь этой темы.
Чуть-чуть теории (всего один абзац!)
Файлы в операционной системе — это не более, чем ссылки на определённые области памяти жёсткого диска. Другими словами, данные хранятся на накопителе в виде последовательностей нулей и единиц, например «01001001». Чтобы получить доступ к этим данным, операционная система создаёт ссылку (link), которую пользователь видит как «файл». Назовём его «number.txt». Эту структуру можно сравнить с веб-ссылкой: к примеру, habr.com указывает на IP-адрес 178.248.233.33, по которому мы получаем доступ к содержимому сайта. Подобно этому, файл number.txt на рабочем столе, на самом деле, — это только ссылка, указывающая на область в памяти диска допустим 0x7ffd3b56a4d0, где находятся данные «01001001». Всё, что видит пользователь, — это интерфейс, «ярлык», который позволяет обращаться к данным по нужному адресу. Но не надо путать это с тем, что сам Windows называет ярлык, об этой сущности в данной статье вообще не говорим. Чтобы понять, как работают hard link, проведём небольшой эксперимент на Windows. Для этого потребуется лишь командная строка. Сначала посмотрите, сколько свободного места на жёстком диск. Откройте командную строку Перейдите на рабочий стол командой Создайте файл, например, размером 10 ГБ, используя команду: Попробуйте скопировать файл. После создания копии свободное место уменьшится ещё на 10 ГБ, так что в итоге будет занято 20 ГБ. Логичное поведение, удалим копию. Теперь, воспользовавшись командной строкой, создадим жёсткую ссылку на файл: Отложим в сторону вопрос размера, посмотрим на содержание. Запишем в bigfile.txt некоторую информацию, например, «Это просто статья на SE7ENе, читайте дальше». Откроем hardlink.txt и увидим ту же информацию, потому что hard link, по сути, является тем же файлом с точки зрения операционной системы. XOR — это логическая операция «исключающее или», полезная для создания резервных копий данных. XOR позволяет сравнивать данные побитово, что даёт возможность выявлять изменения. Например можно полностью резервировать 2 диска, имея только один дополнительный. Представим, что у нас есть данные на двух дисках, скажем, «0100» и «1111». XOR-результат этих данных будет записан на третий диск. Диск 1: 0100 Диск 2: 1111 XOR результат: 1011 Теперь можно восстановить любой из трёх дисков, используя другие два. Просто проведя снова XOR операцию над оставшимися двумя дисками. Это позволяет создавать экономные и надёжные резервные копии. По данному принципу работают массив RAID 5. Если бы мы использовали AND (логическое и) он же RAID 1 (зеркало), то для резервирования 2-х дисков нам бы потребовалось 2 других диска, экономия на лицо. То всё присказка была. Теперь то, для чего писалась эта статья. Комбинация XOR и Hard link даёт отказоустойчивый механики для резервного копирования и работы со снимками состояний. Представьте, что у нас есть два файла. Пусть это будут «Файл А» (1 ГБ) и «Файл Б» (2 ГБ). Допустим первого ноября изменения были внесены только в «Файл А», а в «Файл Б» остался прежним. При традиционном резервном копировании второго ноября пришлось бы копировать оба файла целиком, что заняло бы дополнительно 3 ГБ. Однако сравнив hash суммы файлов, мы определяем какой файл был изменён и записываем только его, в нашем случае «Файл А» (1 ГБ), а для «Файла Б» создаём hard link на его предыдущее состояние. Это позволяет сохранять состояние файловой системы полностью, с детализацией на каждый день, затрачивая место только на изменённые данные. Это похоже на систему теневого копирования в Windows. Таким образом, комбинация hard links и XOR открывает возможности для создания надёжных резервных копий и экономии дискового пространства. Этот метод позволяет не только сохранить доступ к состоянию системы на каждый день, но и экономить место, ведь на хранение уходит только то, что действительно изменилось.Демонстрация работы hard links
Win + R, затем введите cmd
cd Desktop
fsutil file createnew bigfile.txt 10737418240
. После создания файла на диске уменьшится количество свободного места на 10 Г.
mklink /H hardlink.txt bigfile.txt
На диске не занялось дополнительное место, поскольку hard link не дублирует данные, а просто создаёт ещё одну ссылку на ту же область памяти. Но если выделить оба файла, нажать правую кнопку и выбрать пункт «Свойства», то Windows ошибочно просуммирует размеры файлов как 20 ГБ, так как каждая hard link учитывается как полноценный файл с размером, хотя физически данные занимают лишь 10 ГБ, что видно из количества занятого места на диске.
Удалим bigfile.txt. Но hardlink.txt по-прежнему работает (с ярлыками и символьными ссылками так не получится), это возможно, поскольку hard link указывает на данные напрямую, а не на конкретное имя файла. Пока существует хотя бы один hard link на данные, файл продолжают занимать место на диске. Если удалить все hard link — место освобождается.XOR и резервное копирование
Вот пример, как это работает:Hard links и XOR для резервного копирования
Но данные уязвимы к потере из-за выхода из строя накопителя. Поэтому пользуемся программным, аппаратным или собственным RAID, написанном на Python, для создания избыточности и повышения безопасности:def xor_files(file_a, file_b, file_xor):
with open(file_a, 'rb') as infile, open(file_b, 'rb') as maskfile, open(file_xor, 'wb') as outfile:
while True:
byte = infile.read(1)
mask_byte = maskfile.read(1)
if not byte or not mask_byte:
break
# XOR каждого байта файла с байтом маски
outfile.write(bytes([byte[0] ^ mask_byte[0]]))
# Пример использования
input_file="original_file.txt" # Исходный файл
mask_file="mask_file.txt" # Маска-файл
output_file="xor_output.txt" # XOR-файл
xor_files(file_a, file_b, file_xor)