Дедупликация данных в Windows Server - это механизм файловой системы, который находит одинаковые фрагменты содержимого внутри разных файлов и хранит каждый такой фрагмент физически один раз. Файлы при этом выглядят для пользователей и приложений совершенно обычно: они открываются, читаются и перезаписываются штатными средствами, а весь трюк происходит ниже уровня приложений, в драйвере фильтра и фоновой службе оптимизации. Технология появилась в Windows Server 2012, наследуя идеям исследовательских прототипов Microsoft по построению блочных хранилищ, и с тех пор остаётся одним из самых эффективных способов уместить растущие объёмы на файловых серверах без закупки новых дисковых полок и без изменения привычных сценариев работы пользователей. В типовых условиях она даёт экономию от двух до десяти раз в зависимости от природы данных, при этом требуя аккуратного планирования памяти и трезвого понимания границ своей применимости.
Разбиение файлов на чанки переменного размера
В отличие от наивных схем, где файл режется на блоки фиксированного размера, дедупликация Windows Server использует чанки переменной длины, в среднем от 32 до 128 КБ. Границы этих чанков определяются не смещением от начала файла, а самим содержимым данных. Для этого применяется скользящий отпечаток Рабина - дешёвая в вычислении хеш-функция, которую можно инкрементально обновлять при сдвиге окна на один байт, не пересчитывая весь буфер заново: из значения хеша алгебраически вычитается вклад уходящего байта и добавляется вклад приходящего, что делает сканирование гигабайтов потоков практически линейным по времени.
Процесс выглядит так. Движок скользит по потоку байтов небольшим окном и после каждого сдвига проверяет значение отпечатка. Когда отпечаток попадает в заданную маску, например, его младшие биты совпадают с определённым шаблоном, в этой точке ставится граница чанка. Поскольку маска встречается на псевдослучайных данных с известной вероятностью, средняя длина чанка оказывается статистически предсказуемой, но сами границы жёстко привязаны к содержимому потока, а не к позиции. Дополнительно действуют ограничения минимального и максимального размера: слишком короткие куски не создаются, чтобы не раздувать метаданные сверх всякой пользы, а чересчур длинные принудительно разрываются, чтобы не терять гранулярность поиска повторов на почти совпадающих файлах.
Именно привязка к содержимому объясняет знаменитый тест со вставкой одного байта в начало файла - классический экзамен любой дедуплицирующей системы. При блоках фиксированного размера такая вставка сдвинула бы все последующие данные относительно сетки границ, каждый блок получил бы новое содержимое, стал бы уникальным, и дедупликация обнулилась бы полностью. В схеме с переменными границами отпечаток Рабина после вставленного байта довольно быстро снова находит знакомые шаблоны маски в потоке, и почти все дальнейшие границы совпадают с прежними, как будто сдвига и не было. Меняется только первый чанк, возможно ещё пара соседних, а остальная масса данных распознаётся как уже знакомая и повторно не хранится. Свойство называется выравниванием границ по содержимому, или контентно-зависимой нарезкой, и ради него вся схема переменных чанков и строится, несмотря на более сложную реализацию по сравнению с тривиальной фиксированной сеткой.
Хеши SHA-256 и общий chunk store
Каждый полученный чанк подписывается криптографическим хешем SHA-256. Вероятность случайной коллизии у этого алгоритма настолько мала, что система считает равенство хешей доказательством равенства содержимого - это стандартный компромисс всей индустрии дедупликации, отказавшейся от побайтового сравнения ради скорости. Хеши вместе с указателями на физическое расположение данных складываются в специальное системное хранилище на томе - так называемый chunk store.
Физически чанки лежат в каталоге System Volume Information внутри поддерева Dedup, упакованные в крупные контейнерные файлы. Доступ к этому каталогу закрыт даже администраторам в обычных режимах, и это сделано намеренно: целостность хранилища критична, ведь на его содержимое ссылаются сотни тысяч обычных файлов, один случайно изменённый байт может исказить сразу много документов. Одинаковый чанк, встретившийся в десяти виртуальных дисках и пятистах офисных документах, записан на диск ровно один раз, а все остальные вхождения - это компактные отметки в метаданных, связывающие логический диапазон файла с записью в хранилище.
Поверх собственно данных хранилище сжимается. Чанки, которые и так хранятся в единственном экземпляре, дополнительно проходят через алгоритм компрессии в момент помещения в контейнер, что даёт ещё заметную прибавку к суммарной экономии, особенно на текстах, журналах и системных компонентах. Сам chunk store периодически обслуживается сборкой мусора: чанки, на которые больше не ссылается ни один файл после очередных удалений, помечаются недостижимыми и вытесняются при следующем проходе обслуживания, а контейнеры уплотняются, освобождая физическое пространство тома.
Reparse points вместо файлов
После оптимизации исходный файл физически перестаёт хранить свои данные в обычных экстентах NTFS. На его месте остаётся компактная заглушка - reparse point, содержащая карту ссылок на чанки из общего хранилища. Драйвер дедупликации подключается к стеку файловой системы как фильтр: когда приложение читает оптимизированный файл, драйвер перехватывает запрос, разворачивает карту, поднимает нужные чанки из chunk store, при необходимости распаковывает их и отдаёт приложению цельный поток байтов - бит в бит тот, который был записан изначально. Служба также поддерживает горячий кэш часто запрашиваемых чанков в памяти, поэтому повторные чтения популярных данных заметно ускоряются.
Для приложений всё это прозрачно. Файл имеет полный логический размер, корректные метки времени и атрибуты, открывается любыми API без особых флагов. Разница заметна лишь в том, что занятое на диске место, показываемое старыми утилитами, выглядит необычно малым, а холодное чтение после долгого простоя может идти медленнее обычного последовательного. Запись работает симметрично: изменённые области файла нарезаются заново, новые чанки сверяются с хешами хранилища, и только действительно уникальное содержимое занимает свежее место на диске. При копировании оптимизированного файла на другой том без поддержки дедупликации он собирается на лету в полный вид, поэтому формат не запирает данные внутри конкретного сервера.
Фоновая пост-обработка по расписанию
Ключевое архитектурное решение Windows-дедупликации - отказ от инлайн-режима, когда данные обрабатывались бы синхронно в момент записи. Оптимизация наступает постфактум, фоновыми заданиями. Это принципиально снимает нагрузку с горячего пути ввода-вывода: приложения пишут файлы в обычном виде на полной скорости дисковой подсистемы, а тяжёлая работа по нарезке и хешированию откладывается на часы, когда сервер относительно свободен.
Планировщик предлагает три типовых задания. Задание оптимизации сканирует файлы, подходящие под политику: по умолчанию игнорируются файлы младше заданного возраста, чтобы не трогать активно редактируемые документы, и файлы из исключённых расширений и папок, которые администратор задаёт по своему усмотрению. Задание сборки мусора вычищает осиротевшие чанки после удаления файлов. Задание глубокой очистки проверяет контрольные суммы, поджимает и чинит сам chunk store, защищая его от скрытых повреждений. Для каждого задания задаются часы работы, приоритет ввода-вывода и пределы потребления процессора и памяти, так что в рабочее время дедупликация способна крутиться в приглушённом режиме, почти не мешая пользователям, а полная скорость включается ночью и в выходные.
Управление ведётся через PowerShell. Включение механизма на томе выполняется командой Enable-DedupVolume с указанием типа использования - Default, HyperV или Backup, причём каждый профиль по-своему настраивает минимальный возраст файлов и списки исключений. Запуск оптимизации вне расписания делает Start-DedupJob, а мгновенное состояние показывает Get-DedupStatus: там выводятся свободное и занятое пространство тома, совокупная экономия в байтах и главная цифра - поле SavingsRate, процент сэкономленного места. Именно по нему администратор быстро оценивает, окупается ли механизм на конкретном томе или данные оказались по природе уникальными и лишь расходуют память хеш-таблиц.
Где экономия максимальна
Характер данных решает практически всё, и рекордные показатели традиционно принадлежат библиотекам виртуальных дисков и образов.
- VDI-инфраструктуры: сотни рабочих столов, развёрнутых из немногих золотых образов, имеют почти идентичную системную часть, и такие тома ужимаются в 3-10 раз, а с профилем HyperV механизм официально поддерживается даже на томах с живыми VHDX для виртуальных машин.
- Библиотеки ISO и дистрибутивов программ: десятки сборок одной системы или редакций одного пакета различаются на считанные проценты байтов, поэтому складываются друг в друга почти даром.
- Департаментские файловые помойки: типовая общая папка отдела даёт экономию два-три раза, потому что одни и те же шаблоны договоров, презентации, инструкции и вложения из почты кочуют по личным каталогам сотрудников десятками копий годами.
- Папки разработчиков и артефактов сборки: промежуточные результаты компиляции, пакеты и виртуальные окружения повторяют друг друга почти целиком между версиями и ветками.
Хуже всего дедуплицируются уже сжатые или зашифрованные данные - фотографии, видеоархивы, готовые контейнеры архиваторов, - поскольку в их потоке повторов почти не остаётся после энтропийного кодирования. Измерить потенциал заранее, ничего не меняя на сервере, позволяет штатная утилита DDPEval: она прогоняет анализ реальной выборки тома и честно предсказывает будущий SavingsRate ещё до включения роли, что избавляет от разочарований и сюрпризов после внедрения.
Цена вопроса, ограничения и отличие от NTFS-сжатия
Бесплатной экономия не бывает, и расплачиваться за неё приходится тремя валютами. Первая - оперативная память: хеш-таблицы и кэш метаданных желательно удерживать в RAM, иначе каждый поиск чанка превратится в случайное чтение с диска; практики рекомендуют выделять службе заметный объём памяти, растущий пропорционально миллионам чанков на томе. Вторая - отзывчивость при холодном чтении: первый проход по оптимизированным файлам требует разворачивания карт reparse point и подъёма чанков из контейнеров, что медленнее прямого последовательного чтения, особенно на механических дисках, и лишь кэш смягчает этот эффект. Третья - само хранилище: chunk store становится единой опорной структурой тома, его повреждение затрагивает сразу все оптимизированные файлы, поэтому регулярные задания проверки контрольных сумм и исправное резервное копирование обязательны, а бэкап таких томов выполняется в уже собранном виде и раздувается до полного логического размера.
По ограничениям механизм не предназначен для горячих баз данных и постоянно открытых больших файлов - серверы SQL и почтовые хранилища официально исключены из поддерживаемых сценариев за редкими исключениями профиля виртуализации. Действуют и лимиты масштаба: долгое время поддерживались тома до 64 ТБ и отдельные файлы примерно до терабайта, а в более свежих выпусках сервера границы расширились, однако сам принцип умеренности сохраняется - чем крупнее том, тем больше памяти съедают хеш-таблицы и тем дольше длятся задания обслуживания. Дедупликация недоступна на загрузочном томе и на томах с некоторыми файловыми структурами, что стоит учитывать при проектировании сервера.
От привычного NTFS-сжатия дедупликация отличается принципиально. Сжатие работает внутри одного файла и синхронно в момент записи: оно уменьшает каждый файл по отдельности, но ничего не знает о повторах между файлами и потому бессильно против сотен копий одного документа. Дедупликация, наоборот, работает поперёк всего тома и находит именно межфайловые дубликаты, получая выигрыш там, где сжатие пасует. Механизмы мирно сосуществуют на одном томе, хотя конкретный файл обрабатывается по одному из путей. Наконец, о мобильности данных: скопированный на обычный том или выгруженный в облачное хранилище файл автоматически собирается обратно в полный вид, так что дедупликация остаётся локальной особенностью тома и не создаёт зависимости от конкретного сервера при миграции.