Перейти к содержанию

Фоновые процессы

Страница объясняет, какую работу S3R выполняет вне обработки запросов: какие есть фоновые процессы, что запускает каждый из них, как их запустить или приостановить вручную и как устроен контроль целостности данных на дисках. Она нужна администратору, который разбирает состояние кластера по метрикам и журналу или готовит обслуживание.

Коротко

  • Фоновый процесс запускается изменением таблицы или наступлением срока, а не только таймером. Шаг, завершившийся ошибкой, повторяется с растущей паузой.
  • Контрольные суммы проверяются при каждом чтении. Повреждённый фрагмент клиенту не отдаётся и восстанавливается по остальным фрагментам полосы.
  • Недостающие и повреждённые фрагменты ищут и перестраивают процессы resync_queue, resync и scrub, согласованность строк в таблицах проверяет catalog. Вместе они называются фоновым контролем целостности и приостанавливаются одним переключателем repair_mode.

Фоновые процессы

Работу, которая не выполняется в ходе обработки запроса, ведут фоновые процессы. Процесс выполняет свою работу шагами. Шаг запускается одним из трёх событий:

  • изменением таблицы;
  • наступлением сохранённого срока;
  • резервным таймером — на случай пропущенного уведомления.

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

Перечень процессов

Имя процесса — то, под которым его принимает эндпоинт /-/debug/run (см. Запуск и приостановка вручную).

В описаниях встречаются три понятия:

Группы размещения и место на дисках

Имя Назначение
group работа с жизненным циклом групп этого инстанса: первые и запасные экстенты участников, запечатывание, освобождение экстентов, сверка участников, замена участника на выводимом или вышедшем из строя диске и получение новой группы
reconcile сверка вида группы с каталогом: освобождение позиций блоков удалённых объектов и построение вида
extentgc сборка мусора экстентов: пометка экстентов, все блоки которых свободны дольше refill_after_s, как пустых. Процесс запускается к сроку окончания карантина первого освободившегося блока; освобождает экстенты процесс group
diskstat повторная передача числа свободных экстентов каждого диска в таблицу s3r_disk_free, если прежняя передача не удалась

Контроль целостности (подробно — в разделе Контроль целостности)

Имя Назначение
resync_queue передача строк очереди ресинхронизации владельцам групп; выполняется на мастере каждого репликасета
resync сканирование отстающих экстентов, записанных в extents_behind группы, и сканирование всех групп по запросу проверки: восстановление недостающих фрагментов по сохранившимся
scrub проверка согласованности данных и фрагментов чётности в группах размещения
catalog сверка каталога: проверка его согласованности и восстановление производных записей, например строк директорий над существующими объектами. Сведения о повреждённых полосах процесс берёт из их реестра, а не с дисков. Сканирование выполняет мастер каждого репликасета над строками своего репликасета; на реплике процесс ничего не делает

Бакеты, директории и загрузки

Имя Назначение
bucketgc очистка удалённых бакетов на координаторе кластера: удаление строк бакетов, помеченных удалёнными, и затем самих бакетов (см. Удаление бакета)
dirgc сборка мусора директорий: удаление строк опустевших директорий
mpugc сборка мусора составных загрузок: мастер каждого репликасета прерывает хранящиеся у него незавершённые составные загрузки старше mpu_abort_incomplete_after_s. Загрузки бакета, помеченного удалённым, удаляет очистка этого бакета
tenant создание и удаление таблиц тенантов
dedup перенос сведений о совпадениях содержимого в индекс дедупликации (см. Дедупликация)

Жизненный цикл и площадки

Имя Назначение
lifecycle применение правил жизненного цикла: мастер каждого репликасета проходит по объектам и загрузкам своего репликасета. Версия, которая перестала быть текущей после решения о её удалении, остаётся до следующего прохода
transition перенос объектов между ярусами по правилам жизненного цикла
siterepl досылка объектов на площадки, где их ещё нет (см. Репликация между площадками)

У нескольких процессов есть режимы, которые задаются параметром mode:

Имя для /-/debug/run Назначение
group?mode=compare немедленный шаг процесса group, в том числе сверка участников после монтирования групп
siterepl?mode=requeue повторная постановка в очередь досылки недосланных копий, найденных по столбцу placements
dirgc?mode=unchecked удаление строк директорий без предварительной проверки на пустоту; только для испытаний

Шаг resync_queue, запущенный через /-/debug/run, передаёт и отложенные строки.

Как выполняются правила жизненного цикла

Правила выполняет фоновый процесс lifecycle. Он периодически сканирует объекты и вычисляет одним сканированием и удаления, и переходы.

После перезапуска инстанса или смены мастера репликасета удаление по правилам может задержаться на время до одного интервала процесса lifecycle, то есть до часа. Проверить действие правил, не дожидаясь очередного сканирования, можно через диагностический эндпоинт: запрос /-/debug/run/lifecycle, отправленный мастеру каждого репликасета, запускает проход сразу.

Темп удаления ограничен. Перед каждым удалением версии и каждым прерыванием загрузки процесс lifecycle проверяет очередь сообщений об удалённых фрагментах (очередь процесса chunkgc):

  • если очередь заполнена больше чем наполовину, процесс приостанавливается;
  • он продолжает работу, когда в очереди остаётся половина сообщений или меньше;
  • вторая половина очереди остаётся для удалений по запросам клиентов.

Поэтому при массовом истечении срока объекты удаляются с той скоростью, с какой владельцы групп размещения обрабатывают сообщения, и часть объектов удаляется позже срока, который задаёт правило.

Версия, срок перехода которой наступил, ставится в очередь s3r_t<N>_transition. Фоновый процесс transition переписывает её данные в группу яруса нового класса тем же путём, что и запись, обновляет строку объекта и добавляет прежние фрагменты в очередь сборки мусора.

Очистка после удаления бакета

Недоступный мастер останавливает очистку

Если мастер одного из репликасетов недоступен, очистка ждёт, пока он не вернётся или не будет исключён из кластера. Всё это время имя бакета и занятое им место не освобождаются.

Пустой бакет операция DeleteBucket помечает удалённым одной записью Raft и после этого отвечает успехом. Строки бакета удаляет фоновый процесс bucketgc на координаторе кластера:

  1. Ждёт, пока пометку применят мастеры всех репликасетов.
  2. Удаляет строки бакета на каждом мастере.
  3. Последней удаляет строку самого бакета.

Объекты удаляются так же, как при удалении через S3, с возвратом позиций блоков их данных и учёта квот; блокировки объектов эту очистку не останавливают.

Пока очистка не закончена:

  • создание бакета с тем же именем отвечает OperationAborted (409);
  • бакет учитывается в квотах тенанта и своего владельца на число бакетов;
  • пользователя, который владел бакетом, уже можно удалить.

Ход очистки виден в журнале координатора:

Строка журнала Что означает
bucketgc: waiting for <инстанс> to apply the marks процесс ждёт, пока инстанс применит пометку
bucket <id> of tenant <id> is collected очистка закончена

Контроль целостности

Контроль целостности отвечает за то, чтобы каждый участник группы хранил именно тот фрагмент, который указан в каталоге, и чтобы этот фрагмент читался. Он складывается из проверки при чтении и трёх фоновых процессов.

Механизм Что находит Когда работает
Проверка контрольных сумм фрагмент, повреждённый на диске после записи при каждом чтении
resync_queue фрагмент, который участник не принял при записи когда в очереди ресинхронизации есть строки
resync фрагмент, которого нет на месте или который лежит под чужим ключом после замены или переформатирования диска и по запросу проверки
scrub расхождение данных и фрагментов чётности, недостающий или повреждённый фрагмент постоянно, один обход яруса за scrub_period_s

Недостающий фрагмент во всех случаях перестраивается по остальным фрагментам полосы.

Контрольные суммы

Каждый фрагмент хранится вместе с контрольными суммами:

  • заголовок защищён своей суммой;
  • массив сумм защищён суммой в заголовке;
  • каждый участок содержимого защищён своей записью в массиве.

Контрольные суммы проверяются при каждом чтении, а не только фоновым процессом. Фрагмент, не сошедшийся с контрольной суммой, не отдаётся клиенту и восстанавливается по остальным фрагментам полосы.

Очередь ресинхронизации: процесс resync_queue

Фрагмент, который участник не принял при записи, попадает в очередь ресинхронизации (см. Кворум записи). Строки очереди обрабатывает процесс resync_queue.

За один шаг процесс читает одну страницу строк каждого тенанта и передаёт строки разных групп их владельцам одновременно, держа открытыми не больше 16 запросов. Сроки шага:

  • Новые запросы шаг отправляет не дольше 10 с. Поэтому приостановка и остановка сервиса не ждут, пока очередь опустеет.
  • Владелец отвечает не позже чем через 5 с и сообщает, какие строки успел обработать. Остальные процесс отправляет снова без паузы.

Перестроенный фрагмент участник записывает в пустую позицию блока или поверх фрагмента, размещённого не позже перестраиваемого, например фрагмента удалённого объекта. Фрагмент, размещённый позже, перестроение не затирает: это запись другого объекта, которая тем временем заняла эту позицию блока.

Что происходит, когда участник недоступен:

  • Если для перестроения нужен участник на инстансе, который Raft считает недоступным (Offline), строки этой группы откладываются. Они ждут, пока не изменится доступность инстансов или эпоха группы.
  • Сбой при доступном инстансе за отключение не принимается. Строки группы отправляются снова с нарастающей паузой, но не реже раза в минуту.

Ресинхронизация: процесс resync

Процесс resync сравнивает ключ в позиции блока группы с тем, что записано в каталоге, и перестраивает фрагмент, которого нет или который лежит под чужим ключом.

Сканирует группу он только в двух случаях:

  1. Участнику не хватает экстентов, в которые группа уже писала. Так бывает после замены или переформатирования диска, а также когда монтирование освободило экстент с повреждённым заголовком. Такие экстенты называются отстающими. Владелец записывает их в поле extents_behind строки группы прежде, чем участник их выделит. Процесс проверяет позиции блоков только этих экстентов и только на этом участнике.
  2. Администратор запросил проверку (POST /v2/repair). Тогда сравниваются все участники во всех позициях блоков каждой группы.

На кластере без нагрузки процесс resync ничего не сканирует. Фрагментов, на которые не ссылается ни одна строка, при этом не остаётся: место освобождается изменением строки, а не отдельной уборкой.

Проверка целостности данных: процесс scrub

Процесс scrub проверяет избыточное кодирование: заново вычисляет фрагменты чётности по k фрагментам данных и сравнивает результат с сохранёнными m фрагментами. Фрагменты полосы он читает одновременно.

Что процесс делает с находками:

  • Фрагмент, которого у участника нет или который не прошёл проверку контрольных сумм, процесс перестраивает по уже прочитанным фрагментам, не читая полосу второй раз.
  • Полосу, от которой осталось меньше k фрагментов, процесс записывает в реестр повреждённых полос как утраченную — если ответили все участники.
  • Участника, которого заполняет процесс resync, процесс scrub пропускает. Это замена, ещё не выделившая экстенты, и участник с отстающими экстентами из списка extents_behind.

Период проверки. Параметр scrub_period_s записи яруса в erasure задаёт период: за этот срок процесс читает и сверяет каждую полосу яруса один раз. Период по умолчанию — 14 дней. Это около 13 МБ/с чтения на заполненный жёсткий диск объёмом 16 ТБ и около 3 МБ/с на заполненный SSD объёмом 3,75 ТБ. Ярусу на флеш-памяти можно задать период короче.

Темп. Процесс распределяет чтение по периоду равномерно:

  • Шаг читает не больше 1000 полос и не больше 64 МиБ фрагментов. Оба предела — константы.
  • Следующий шаг того же яруса ждёт ту долю периода, какую прочитанное составляет от объёма групп яруса. Поэтому на кластере без нагрузки процесс читает столько, сколько требует период, и не больше.
  • Если последняя проверка какой-либо группы яруса старше его периода, процесс читает с паузой 10 мс между шагами, пока не нагонит срок.

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

Повреждение данных на диске

Фрагмент или заголовок экстента, который не прошёл проверку контрольной суммы, означает повреждение данных на диске после записи. Участник отвечает, что такого фрагмента у него нет, поэтому любое чтение восстанавливает его по остальным.

Кто записывает исправный фрагмент на место:

Кто нашёл повреждение Что происходит Где учитывается
Чтение клиента участник сразу просит владельца группы перестроить фрагмент и записать его на место метрика s3r_chunks_put_back_total с меткой worker="read"
Проверка фрагмент записывает на место процесс scrub —

Каждый случай повреждения участник учитывает один раз, сколько бы раз фрагмент ни читали до записи на его место:

  • в метрике s3r_disk_crc_failures_total своего диска;
  • в журнале, на уровне warn.

Правило S3rDiskBitrot сообщает о диске, где повреждение случилось за последний час.

Повторное повреждение одного места

Заголовок фрагмента хранит число таких восстановлений. Если фрагмент испортился снова после трёх восстановлений (число не настраивается), участник больше не просит его перестроить и пишет в журнал на уровне error: это место диска выходит из строя. Такой фрагмент записывает только процесс scrub.

Обычное восстановление фрагментов, которых не оказалось на месте после записи или отказа диска, учитывается отдельно, в метрике s3r_chunks_put_back_total, и в журнал попадает только на уровне verbose.

Нагрузка от контроля целостности

На диски. Ввод-вывод восстановления каждый диск выполняет по одной операции одновременно, от кого бы они ни пришли. К нему относятся чтение и запись при перестроении, чтение процессом scrub и проверки процесса resync. На запросы клиентов это ограничение не распространяется, поэтому участник, вернувшийся после отключения, получает пропущенные фрагменты наряду с записями клиентов.

На метаданные. Строки каталога, которые ссылаются на группу, процессы resync и scrub читают по одному бакету vshard, с первого до последнего, страницами не больше 1000 строк. Бакет vshard — единица распределения строк между репликасетами, а не бакет S3.

  • Страница не выходит за границы своего бакета, поэтому последняя страница бакета бывает короче.
  • Каждую страницу отдаёт мастер репликасета, на котором бакет находится в момент чтения.
  • Процесс проверяет позиции блоков одной страницы и только потом запрашивает следующую. В памяти он держит одну страницу группы, а не всю группу.
  • Полная страница занимает транзакционный поток мастера примерно на половину миллисекунды.
  • После полной страницы процесс выжидает 10 мс, после неполной — соответственно меньше.

Шаг процесса resync читает по одной странице каждой группы, которую нужно сканировать. Следующий шаг выполняется сразу за ним, пока сканирования не закончатся. Сбои обрабатываются так:

  • страница, которую не удалось прочитать, читается снова при следующем шаге;
  • сканирование, которое не удалось, повторяется с нарастающей паузой;
  • если бакет перешёл на другой репликасет между двумя страницами, сканирование дочитывает его на новом мастере с того места, где остановилось.

Когда прочитаны все бакеты, сканирование отмечает группу ресинхронизированной, а проверка записывает своё окончание.

Приостановка контроля целостности

Фоновый контроль целостности приостанавливает и возобновляет администратор (см. Приостановка фонового контроля целостности).

Пока контроль приостановлен, недостающие фрагменты не восстанавливаются

Процессы catalog, resync, resync_queue и scrub не выполняются, а строки очереди ресинхронизации накапливаются. Шаг такого процесса, запущенный через /-/debug/run, в это время тоже ничего не делает.

Контрольные суммы при этом по-прежнему проверяются при каждом чтении.

См. также