Skip to content

Latest commit

 

History

History
270 lines (182 loc) · 15.1 KB

file-structure.md

File metadata and controls

270 lines (182 loc) · 15.1 KB
title
Структура файлов

Здесь описаны файлы, которые использует приложение, и формат их содержимого. Используемые типы данных находится в файле с общими типами данных.

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

Общая структура файловой системы выглядит следующим образом (относительно рабочей директории):

  • taskflux.settings.json
  • data
    • tflux.log
    • log
      • xxxxxxxxxxxxxxxxxxx.log
    • tflux.metadata
    • tflux.snapshot
    • temp

Вспомогательные структуры данных

QueueRecord

Представляет собой одну запись из очереди. Состоит из полей: ID, приоритет и данные записи, идущих друг за другом.

Поле ID Приоритет Данные
Тип UInt64 Int64 Buffer

taskflux.settings.json

Описание

Это файл конфигурации приложения. Конфигурация хранится в формате json. Файл не обязателен, и если отсутствует, то ничего прочитано не будет.

data/log

Описание

Для хранения записей используется сегментированный лог. В этой директории содержатся сегменты этого лога.

Каждый файл лога именуется xxxxxxxxxxxxxxxxxxx.log, где xxxxxxxxxxxxxxxxxxx - это индекс (LSN), с которого начинаются все записи в логе. Например:

  • 0000000000000000000.log - самый первый файл сегмента лога, т.к. он начинается с записи, индекс которой 0;
  • 0000000000645261357.log - сегмент, записи которого начинаются с индекса 645261357.

Длина названия фиксированная - 23 = len(LSN + .log)

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

Дальше команды будут называться Дельта - изменение в состоянии приложения.

Формат файла

Общий формат файла:

Маркер файла Версия Маркер записи Терм Чек-сумма Данные Маркер конца файла
Byte[4] Int32 Byte[4] Int32 UInt32 Array<Byte> Byte[4]

Поля:

  • Маркер файла - специальный маркер для изначальной проверки, что переданный файл является логом. Равен 0x12 0x76 0xAD 0x55;
  • Версия - версия структуры файла;
  • Маркер записи - маркер, используемый для проверки того, что дальше идет запись. Равен 0xAA 0xF5 0x34 0xC4;
  • Терм - терм, которому принадлежит запись;
  • Чек-сумма - чек-сумма, подсчитанная для данных дельты (следующее поле, без длины). Вычисляется для данных в поле Данные (без длины);
  • Данные - содержимое команды, которое мы храним.
  • Маркер конца файла - маркерные байты, которые означают окончание файла лога. Равен 0x00 0x00 0x00 0x00.

Поля Маркер-записи, Терм, Чек-сумма, Данные образуют одну запись. Эти поля идут в файле последовательно друг за другом. Для их разделения используется маркер записи, а не отдельное поле длины, для большей производительности.

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

Замечание: поле Данные должно быть выравнено по границе 4 байт. Если длина содержимого данных не кратна 4 байтам, то в конец добавляются нулевые байты до размера кратного 4 байтам. Примеры:

Длина данных (байты) Дополнение (байты)
1 3
34 2
1024 0
2051 1

Создание и удаление сегментов

Файлы сегментов могут создаваться и удаляться в процессе работы:

  • При запуске приложения в первый раз создается файл сегмента 0000000000000000000.log;
  • Когда размер файла сегмента превышает указанный лимит, то создается очередной файл сегмента - CURRENT LAST LSN + 1 + .log, где CURRENT LAST LSN - последний LSN текущего сегмента;
  • При откате незакоммиченных записей лога, файлы могут удаляться, если требуется переписать данные из уже законченного сегмента.

Для файлов сегментов указываются 2 параметра:

  • soft limit - мягкая граница размера файла в байтах.
  • hard limit - жесткая граница размера файла в байтах.

Новые файлы сегментов создаются при соблюдении любого следующего условия:

  • soft limit < current segment size && commit index == last segment LSN;
  • hard limit < current segment size.

Т.е. новый файл создается:

  • либо когда мягкий предел размера сегмента превышен и все записи закоммичены;
  • либо когда превышен жесткий предел размера сегмента.

Дельта

Дельта : Изменение в состоянии приложения

На данный момент поддерживаются следующие дельты:

  • CreateQueue - Создание очереди
  • DeleteQueue - Удаление очереди
  • AddRecord - Добавление записи в очередь
  • RemoveRecord - Удаление записи из очереди

Для каждого из типа определены собственные форматы данных и маркеры.

CreateQueue

Создание новой очереди.

Формат:

Маркер Название очереди Реализация Максимальный размер очереди Максимальный размер сообщения Диапазон ключей
Byte('C') QueueName Int32 Int32 Int32 Nullable<Pair<Int64, Int64>>

Поле Реализация содержит код реализации, который нужно использовать

DeleteQueue

Удаление существующей очереди

Формат:

Маркер Название очереди
Byte('D') QueueName

AddRecord

Добавить в очередь новую запись

Формат:

Маркер Название очереди Ключ Сообщение
Byte('A') QueueName Int64 Buffer

RemoveRecord

Удалить запись из очереди по указанному Id

Маркер Название очереди Id
Byte('R') QueueName UInt64

data/tflux.snapshot

Описание

В этом файле хранится готовый слепок приложения - все очереди с их параметрами и записями.

Содержит данные о всех существовавших очередях в приложении на момент создания файла. Порядок хранения очередей не задается - могут идти в любом.

Формат данных

Структура файла:

Маркер Последний индекс Последний терм Состояние Чек-сумма
Byte[4] Int32 Int32 Buffer Byte[4]

Поля:

  • Маркер - маркер файла снапшота. Равен 0xB6 0x38 0x0F 0xC9;
  • Последний индекс - индекс последней примененной команды;
  • Последний терм - терм последней примененной команды;
  • Состояние - данные снапшота, представляется массивом байт;
  • Чек-сумма - чек-сумма, вычисленная по всем данным поля Состояние (кроме длины);

Само поле Состояние состоит из сериализованного массива структур QueueData, т.е. там хранится Array\<QueueData>. Эта структура представляет описание одной очереди вместе с ее записями. Формат структуры QueueData представлен ниже:

Название очереди Реализация Последний ID Максимальный размер очереди Максимальный размер сообщения Диапазон ключей Данные очереди
QueueName Int32 UInt64 Int32 Int32 Nullable<Pair<Int64, Int64>> Array<QueueRecord>

Поле Очередь содержит повторяющиеся сериализованные значения всех элементов очереди - пара приоритет-нагрузка. Количество элементов определяется полем Размер очереди.

Поля:

  • Название очереди - название очереди
  • Реализация - код реализации очереди
  • Последний ID - ID последней записи, который был назначен

Замечание: данные в очереди необязательно должны быть в правильной очередности (порядок приоритета), очередь восстанавливается во время старта из этих значений.

data/tflux.metadata

Описание

В этом файле содержатся метаданные, которые необходимы для корректной работы узла в кластере.

Формат файла

Файл занимает немного места и состоит из нескольких фиксированных по размеру полей.

Структура файла:

Маркер Версия Терм Голос Чек-сумма
Byte[4] Int32 Int32 Int32 Byte[4]

Поля:

  • Маркер - специальный маркер файла. Равен 0x5A 0x6E 0xA0 0x12;
  • Версия - версия файла;
  • Терм - последний сохраненный терм;
  • Голос - значение ID узла, за который голосовали последний раз. -1 означает отсутствие голоса. Другие отрицательные значения не принимаются;
  • Чек-сумма - чек-сумма, вычисленная для файла. Вычисляется по всем полям, кроме Маркер.

data/temp

Описание

Эта директория необходима для хранения временных файлов. Например:

  • Временные файлы лога при создании снапшота;
  • Новые снапшоты, которые принимаются от других узлов.

Дополнительно

На все файлы накладываются следующие условия:

  • Если файл существует на момент старта приложения, то либо файл должен быть в корректном состоянии, либо пуст (размер 0);
  • Для расчета чек-суммы (где есть соответствующее поле) используется алгоритм описанный в сетевом протоколе.