ActiveScaleинженерная практика

Классы Active и Cold

Основы basicsactivecoldglacierlifecycle

Коротко. Active — рабочие данные на NVMe/HDD, доступ мгновенный, класс S3 Standard. Cold — архив на ленте, класс S3 Glacier-совместимый, доступ после restore за минуты. Оба класса живут в одном namespace и управляются lifecycle-политиками. Холодный тир дешевле по ТБ, но требует ленточной инфраструктуры и обслуживания.


1. Сравнение

Active Cold
Носитель NVMe / HDD Лента (RAIL)
S3-класс Standard Glacier-совместимый
Доступ сразу после restore (минуты)
Стоимость ТБ выше ниже (вендор заявляет до −80%)
Избыточность erasure coding 2D erasure coding
Типичные данные бэкапы, рабочие наборы, аналитика архив на годы/десятилетия
Ограничения ёмкость время restore, инфраструктура ленты

Разница не в «быстро/медленно», а в модели доступа. Активный класс отвечает на запрос чтения сразу: объект лежит на NVMe или HDD, его фрагменты разложены erasure coding по блоксторам, клиент получает байты в том же TCP-соединении. Холодный класс отвечает на запрос чтения отказом до тех пор, пока объект не восстановлен в дисковый слой — это не деградация производительности, а другое состояние объекта.

Второе отличие — избыточность. В активном классе работает обычное erasure coding; в холодном — двумерное (2D EC), где чётность считается и внутри кассеты, и между кассетами, приводами и библиотеками. Вендор заявляет overhead от 15% и до 40% эффективнее схем «две копии/репликация». Практический смысл для инженера: ремонт холодного объекта обычно требует одной кассеты, а не всей библиотеки.

Третье отличие — цена ошибки планирования. Активный класс расширяется нодами и полками; холодный требует библиотеки, приводов, коннектора и кассет с ротацией. Поэтому «перевести всё в Cold и сэкономить» почти всегда упирается не в стоимость ТБ, а в инфраструктуру и регламент.


2. Как объект попадает в Cold

  1. Приложение пишет объект с классом GLACIER (или lifecycle переводит по возрасту).
  2. S3-сторона ставит работу в очередь.
  3. Объект собирается в том, проходит staging, получает маркер архивации.
  4. Оркестратор выдаёт запрос библиотеке; привод пишет на кассету.
  5. Объект остаётся доступным «логически», но чтение требует restore.

restore возвращает объект в активный/staging-слой; после этого его можно читать как обычный. Для больших объектов поддерживается ranged restore (с 7.1).

Важно, что запись в холодный класс асинхронна по своей природе: PUT завершается, когда объект принят и поставлен в очередь, а не когда кассета физически записана. Между этими моментами объект уже виден в листинге и уже имеет класс GLACIER, но на ленте его ещё нет — он ждёт в дисковом staging. Это нормальный режим, а не сбой; но он означает, что «архив готов» и «объект принят» — разные утверждения, и проверять их надо по-разному.


3. Как выглядит переключение класса на практике

Есть два пути, и они отличаются тем, кто принимает решение.

Путь первый — класс указывает приложение. В запросе PutObject передаётся заголовок x-amz-storage-class: GLACIER. Дальше приложение обязано считать объект архивным: успешный PUT означает «принят и будет архивирован», а не «лежит на ленте». История знает ловушку на этом пути: в версиях до 7.1 переход в GLACIER через механизм управления жизненным циклом (OLM) терял место в учёте ёмкости — объекты уезжали, а цифры расходились. На актуальных сборках это закрыто, но при разборе расхождений в отчётах по ёмкости старые версии надо проверять отдельно.

Путь второй — класс меняет lifecycle по возрасту. Правило вида «объекты под префиксом старше N дней → GLACIER» снимает решение с приложения полностью. Приложение продолжает писать в Standard и не знает, что часть его данных уже на ленте; обнаруживается это только на чтении. Отсюда правило: lifecycle-переход всегда должен сопровождаться проверкой сценария чтения — тем самым restore, о котором приложение может ничего не знать.

Что видит приложение в обоих случаях:

  • PutObject → 200 OK сразу, объект в листинге;
  • HeadObject → 200, в ответе класс GLACIER, размер и ETag на месте;
  • ListObjectsV2 → объект в списке, класс в поле StorageClass;
  • GetObject → отказ с кодом ошибки «объект в архивном состоянии» до выполнения restore.

То есть метаданные остаются «горячими» всегда: листинг, HEAD, проверка размера и ETag работают без обращения к ленте. Это следствие двухслойной архитектуры — access layer с метаданными на NVMe отвечает независимо от data layer. Именно поэтому «объект есть в листинге» ничего не говорит о физическом носителе.

Отдельно про батчирование: с 7.2 объекты уходят на ленту по ёмкости батча, а не только по числу объектов. До этого крупные multipart-объекты могли задерживаться в очереди, потому что «сто штук» и «сто объектов по 20 ГБ» считались одинаково. Если видите, что мелкие объекты уехали, а крупные висят — сначала проверьте версию, потом ищите проблему.


4. Чтение из Cold: что происходит после restore

restore — отдельная операция, а не «первое чтение с задержкой». Она ставит задачу на возврат объекта из ленты в дисковый слой; до её завершения GetObject продолжает отказывать.

Состояний, с которыми придётся иметь дело в эксплуатации, три — и в план восстановления надо закладывать худшее:

Состояние объекта Что делает система Ожидание
Уже в warm-staging (недавно архивировали или восстанавливали) отдаёт с диска секунды
На кассете, кассета в слоте загружает кассету в привод, читает минуты
Кассета вне библиотеки или недоступна restore не может начаться часы и ручная работа

Третий сценарий — не теория: до 7.1 restore мог «зависать» при недоступной кассете или при заполненном дисковом тире, и это лечилось только разбором состояния библиотеки. Сейчас такие ситуации обрабатываются явнее, но кассета, забытая в слоте другого плеча или вынутая оператором, по-прежнему останавливает восстановление.

С 7.1 поддерживается ranged restore — восстановление диапазона байт, а не всего объекта. Для архива это принципиально: если нужно прочитать заголовок контейнера в первых мегабайтах многогигабайтного объекта, нет смысла тянуть его целиком и занимать дисковый тир. Ranged restore возвращает только нужный диапазон, и остальные байты остаются на ленте.

Скорость возврата менялась от версии к версии, и это стоит держать в голове при выборе сборки: 7.2 дала ускорение restore более чем в 5 раз за счёт агрегации запросов по локальности ленты, 7.3 — до 10 раз быстрее для данных, уже находящихся в warm-staging, плюс быстрее освобождает диск после архивации. С 7.2 приоритет отдаётся восстановлению, а не архиву и ремонту; в 7.3 появилась настройка Cold Storage QoS — резервирование приводов отдельно под архив и под restore (включается через поддержку).

Практическое следствие: restore расходует ёмкость дискового тира. Восстановленная копия живёт на дисках, пока она нужна, и при массовом восстановлении архив может упереться не в приводы, а в свободное место активного слоя. Проверять надо оба ресурса.


5. Когда что использовать

Active: - данные, к которым обращаются ежедневно; - бэкапы с быстрым восстановлением; - аналитика/AI, где важна скорость; - рабочие наборы медиа.

Cold: - архив, который нужен «на всякий случай»; - регуляторное хранение; - медиа/научные данные, доступ к которым редкий; - замена «полки с кассетами», но с S3-интерфейсом.

Не стоит: держать в Cold данные, которые нужны каждый день — restore добавит минуты и нагрузку на приводы.


6. Когда Cold не подходит

Ситуация Почему Cold не подходит Что делать вместо
Частый доступ (ежедневно, «горячий» каталог) каждый GET тянет restore: минуты латентности и загрузка приводов Active; в Cold — только то, что реально не читают
Регулярные выборочные чтения по многим объектам restore на каждый объект, дисковый тир заполняется копиями Active или отдельный бакет под рабочую выборку
Много очень мелких объектов архивация идёт батчами по ёмкости, накладные расходы на объект высокие группировать в контейнеры/архивы перед отправкой
Нужен предсказуемый SLA на чтение в секундах физика ленты: загрузка кассеты и позиционирование Active; Cold — только для данных с SLA в часах
Регулятор требует конкретный носитель или офлайн-копию класс Cold сам по себе этого не гарантирует; вопрос к комплаенсу сверять требование с юристами и с поддержкой, не «по аналогии с AWS»
Нет обслуживания библиотеки кассеты, ротация, safety, штрихкоды — это регламент, а не «поставил и забыл» считать стоимость эксплуатации до закупки

Отдельно про удаление: с 7.3 появилась Tape Space Reclamation — повторное использование ёмкости кассет после удаления объектов, ретроспективно и автоматически. До этого удаление освобождало метаданные, но не обязательно место на носителе. Это меняет экономику «архив с истечением срока»: считать ёмкость только по объёму записанных данных нельзя.


7. Экономика: считать надо полностью

  • Стоимость ТБ на ленте ниже, но есть:
  • библиотека, приводы, коннектор;
  • кассеты и их ротация;
  • обслуживание и регламент;
  • время restore и нагрузка на дисковый тир.
  • «До −80%» — вендорская оценка для холодного класса, не «итоговая стоимость владения».

8. Частые ошибки

  1. Путать Cold с бэкапом. Холодный класс — не замена резервному копированию: удаление объекта и lifecycle работают и там.
  2. Не считать безопасность. Object Lock/версионирование нужно настраивать отдельно.
  3. Не проверять restore. План восстановления должен включать тест из холодного класса.
  4. Забыть про кассеты. Свободные кассеты (genscratch), safety и ротация — часть эксплуатации.
  5. Считать класс свойством бакета, а не объекта. Класс задаётся на объект; в одном бакете спокойно живут оба класса, и листинг это показывает.
  6. Ожидать, что PUT в Cold означает «на ленте». Между приёмом и записью на кассету есть окно staging, и оно измеряется не секундами при больших объёмах.

9. Источники


Нужен инженер? Разберу вашу ситуацию и скажу, что делать — по шагам, с проверками.

Обсудить задачу