Перейти к содержимому
Последнее обновление

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

Основные принципы​

Разбиение кэша на фрагменты и механизм предварительной выборки​

Doris разбивает целевые файлы на фрагменты с выравниванием по границам 1 MB. После полной загрузки каждого фрагмента он сохраняется в виде отдельного файла блока в локальной файловой системе. Такое мелкое разбиение позволяет не тратить место на кэширование крупных файлов целиком, а также точнее отслеживать попадания в кэш и управлять вытеснением горячих данных.

Организация каталогов локальных файлов​

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

Пример: если путь к целевому файлу — /remote/data/datafile1, а вычисленный хэш — 12345, путь к соответствующему файлу блока будет следующим:

/cache/123/12345/<offset>

Здесь <offset> — смещение данных этого блока в исходном файле.

Механизм нескольких очередей​

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

ОчередьСодержимоеПриоритетПримечания
Очередь TTLДанные с заданным атрибутом TTLНаивысшийДанные не вытесняются, пока не истечёт TTL. TTL — атрибут уровня таблицы; например, значение 3600 означает, что данные сохраняются в кэше до 1 часа после загрузки. Подходит для небольших часто используемых таблиц, данные которых необходимо постоянно хранить локально.
Очередь IndexИндексные данные (кроме инвертированных индексов)ВысокийИспользуется для ускорения фильтрации при выполнении запросов. Инвертированные индексы помещаются в очередь Normal из-за большого размера.
Очередь NormalОбычные данные (без атрибута TTL)СреднийОчередь, в которой находится большая часть данных.
Очередь DisposableВременные данные (например, данные, считываемые во время Compaction)НаименьшийПосле использования вытесняются в первую очередь.

Механизм вытеснения​

Когда запускается вытеснение​

Условие запускаОписание
Пассивное вытеснение из-за нехватки местаЗапускается, когда заканчивается место на локальном диске или доступные inode либо когда объём кэша достигает настроенного предела ёмкости.
Активное вытеснение при достижении верхнего порогаКогда объём кэша достигает верхнего порога, Doris заранее асинхронно удаляет старые записи кэша, чтобы синхронное вытеснение не блокировало запись.
Вытеснение при сборке мусораЗаблаговременно удаляет следующие устаревшие данные: исходные данные операций Compaction и Schema Change, данные после отката из-за неудачной фиксации загрузки и остаточные данные операций DROP TABLE или DROP PARTITION.
Понижение приоритета после истечения TTLКогда срок действия записи TTL истекает, она перемещается в очередь Normal и участвует в обычном процессе вытеснения LRU.

Стратегия выбора данных для вытеснения​

Соотношение выделяемого пространства: несколько очередей совместно используют дисковое пространство, при этом для каждой очереди задан собственный верхний предел её доли (например, для очереди Normal он составляет 40% общего пространства). Пока другие очереди не израсходовали выделенную им долю, очередь может использовать всё оставшееся пространство. По мере роста объёма данных каждого типа доли постепенно приближаются к настроенным значениям.

Порядок вытеснения: когда в очереди недостаточно места для записи, Doris вытесняет данные, превышающие выделенную долю, в следующем порядке (внутри каждой очереди порядок вытеснения записей определяется LRU):

Disposable → Normal → Index → TTL

Если после вытеснения из других очередей места по-прежнему недостаточно, Doris вытесняет записи из самой целевой очереди по алгоритму LRU.

Рекомендации по предотвращению вытеснения горячих данных​

  • Оставляйте достаточно свободного места на диске: очистка кэша происходит с некоторой задержкой, поэтому всегда нужен запас. На практике ёмкость файлового кэша, примерно в 1.5 раза превышающая объём горячих данных, используемых в запросах, обеспечивает высокую долю попаданий.
  • Изолируйте крупные запросы: направляйте крупные запросы в выделенный кластер, чтобы они не занимали кэш и не снижали долю попаданий для других запросов.

Механизм прогрева​

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

Ручной прогрев​

Можно запустить прогрев для указанной таблицы или раздела либо на основе содержимого кэша другого кластера. Источником данных всегда служит удалённое хранилище (а не другие узлы BE); чтение из кэша других узлов BE при выполнении запроса отдельно обеспечивает механизм чтения из кэша других узлов. Прогрев выполняется следующим образом:

  1. Вы отправляете команду прогрева. Система преобразует целевой объект в набор tablet и распределяет их между соответствующими узлами BE.
  2. Каждый BE последовательно считывает все файлы данных своих tablet и записывает данные в локальный файловый кэш.
  3. Задачи выполняются пакетами объёмом не более 20 GB каждый. После завершения каждого пакета сохраняется контрольная точка, позволяющая возобновить выполнение после прерывания.
  4. Если BE выходит из строя или вы вручную отменяете задание, все узлы BE прекращают скачивание и прогрев завершается.

Состояние задачи (FINISHED / CANCELLED / RUNNING) и общий ход выполнения можно проверить командой SHOW WARM UP JOB. При повторном прогреве той же таблицы и раздела Doris автоматически обнаруживает существующие данные и выполняет инкрементальное обновление, не скачивая повторно уже имеющиеся в кэше данные.

Прогрев при перебалансировке данных​

Когда tablet переносится на новый BE из-за перебалансировки нагрузки (при масштабировании или отказе узла), новый BE отправляет RPC старому BE, чтобы получить метаданные кэша, а затем на их основе повторно скачивает данные в свой локальный файловый кэш. При очистке информации о tablet данные кэша на старом узле заблаговременно вытесняются, освобождая место.

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

Автоматический прогрев между вычислительными кластерами (версия 3.1+)​

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

СпособКогда использоватьОписание
Периодический прогревКогда актуальность данных в реальном времени не критичнаУкажите интервал синхронизации в SQL-операторе WARM UP. Задание периодически синхронизирует новые и изменённые данные указанных таблиц и разделов с целевым кластером.
Прогрев при загрузке данных или CompactionКогда требуется актуальность данных в реальном времениКогда задание загрузки переходит на этап фиксации, BE исходного кластера уведомляет соответствующий BE целевого кластера о необходимости скачать новые данные, отправленные в хранилище. Завершение Compaction запускает аналогичную цепочку уведомлений. FE отвечает за поддержание информации о распределении tablet в целевом кластере.

Разбор сценариев​

Выполнение запросов​

При выполнении запроса файловый кэш обрабатывается следующим образом:

  1. Запрос на чтение от Scanner: после поступления запроса компонент Scanner готовится читать необходимые файлы данных.
  2. Проверка локального кэша: Scanner сначала проверяет локальный файловый кэш, сопоставляя метаданные кэша по пути к файлу и смещению.
  3. Попадание в кэш: если подходящие данные найдены в кэше, система возвращает набор дескрипторов BlockFile, и Scanner считывает данные локально, не обращаясь к удалённому хранилищу.
  4. Промах кэша: для диапазонов, отсутствующих в кэше, Scanner скачивает данные из удалённого хранилища, записывает их в файловый кэш, а затем возвращает. Место освобождается в соответствии с политикой вытеснения. Если явно включено чтение из кэша других узлов, Scanner сначала обращается к файловому кэшу других узлов BE и скачивает данные из удалённого хранилища, только если их нет ни на одном BE.

Загрузка данных​

При загрузке данных файловый кэш обрабатывается следующим образом:

  1. Запись в удалённое хранилище: поступающие данные сначала записываются в удалённое хранилище.
  2. Асинхронная запись в локальный кэш: одновременно Doris асинхронно записывает данные в локальный файловый кэш, чтобы запросы сразу после загрузки могли обращаться непосредственно к кэшу.
  3. Выбор очереди кэша: в зависимости от типа данных и атрибута TTL данные записываются в соответствующую очередь (TTL, Index или Normal).

Выполнение Compaction​

В Doris есть два типа Compaction:

  • Cumulative Compaction: объединяет инкрементальные сегменты данных.
  • Base Compaction: объединяет базовую версию данных (начиная с версии 0) с инкрементальными версиями данных.

Эти два типа Compaction используют разные стратегии записи в кэш:

Тип CompactionСтратегия записи в кэш
Cumulative CompactionРезультирующие данные записываются в файловый кэш одновременно с отправкой в удалённое хранилище, как и при загрузке данных, чтобы ускорить последующие запросы.
Base CompactionПо умолчанию данные записываются в кэш только при наличии достаточного свободного места, чтобы не загрязнять кэш большими объёмами холодных данных. Можно принудительно включить запись, задав параметр BE enable_file_cache_keep_base_compaction_output = true, но это может привести к вытеснению других горячих данных.

При ограниченной ёмкости локального кэша можно включить политику записи только индексов, чтобы данные Segment из результатов Compaction не занимали активно большой объём кэша:

  • enable_file_cache_write_index_file_only=true: применяется ко всем операциям записи rowset в режиме с разделением вычислений и хранения, включая Compaction. Данные Segment активно не кэшируются, но диапазоны, содержащие footer и внутренние индексы Segment, а также отдельные файлы инвертированных индексов по-прежнему записываются в кэш.
  • enable_file_cache_write_base_compaction_index_only=true или enable_file_cache_write_cumu_compaction_index_only=true: ограничивает запись только тех результатов соответствующего типа Compaction, которые иначе были бы записаны в кэш. Файлы Segment пропускаются, а отдельные файлы инвертированных индексов сохраняются, но диапазоны, содержащие footer и внутренние индексы Segment, предварительно не загружаются.

Приоритет параметров, примеры конфигурации и ограничения описаны в разделе Настройка файлового кэша.

В планах: в будущей версии Doris появится адаптивная стратегия записи на основе статистики предыдущих запросов.

Загрузка кэша после перезапуска​

До версии 3.1 порядок элементов очереди LRU не восстанавливался после перезапуска, что приводило к вытеснению горячих данных и снижению доли попаданий.

В версии 3.1 появилась возможность сохранять информацию LRU. Загрузка выполняется следующим образом:

  1. Периодическое сохранение: информация о порядке элементов каждой очереди LRU периодически сохраняется на диск.
  2. Загрузка при перезапуске: при перезапуске узел считывает сохранённые данные с диска, чтобы восстановить состояние очередей кэша.
  3. Полное сканирование диска для проверки полноты: после перезапуска выполняется полное сканирование диска, чтобы устранить расхождения между метаданными и содержимым диска, возникшие в интервале между сохранениями, и обеспечить целостность данных.
  4. Параллельная асинхронная загрузка по запросу: во время полного сканирования диска BE продолжает обслуживать запросы. Если запрос обращается к данным, которые ещё не были просканированы, система загружает их вне очереди, чтобы сократить задержку запроса.

Масштабирование​

Горизонтальное масштабирование с добавлением узлов​

Doris переносит tablet на новые узлы BE посредством перебалансировки. Целевой BE повторно скачивает данные в локальное хранилище на основе метаданных кэша исходного BE, чтобы запросы на новом узле также могли получать данные из файлового кэша. При использовании чтения из кэша других узлов первые операции чтения на целевом BE также могут получать блоки непосредственно из кэша исходного BE ещё до завершения скачивания.

Горизонтальное масштабирование с удалением узлов​

Если после перебалансировки tablet общая ёмкость файлового кэша кластера становится меньше фактического объёма кэшированных данных, механизм вытеснения автоматически удаляет избыточные данные.

Вертикальное масштабирование с увеличением ресурсов​

Способ увеличения ресурсовДействия
Увеличение ёмкости отдельного дискаВыполните следующую команду, чтобы уведомить BE об изменении доступного пространства: curl http://<BE_IP>:<WEB_PORT>/api/file_cache?op=reset&capacity=<new capacity in bytes>
Добавление дисковНе рекомендуется. В настоящее время в Doris не реализовано повторное хэширование и не поддерживается перебалансировка между дисками. Изменение числа каталогов кэша может привести к ошибкам поиска данных в кэше. Если диски всё же необходимо добавить, очистите кэш и при необходимости выполните повторный прогрев.

Вертикальное масштабирование с уменьшением ресурсов​

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

Особенности прогрева после масштабирования​

Горизонтальное масштабирование с добавлением и удалением узлов сопровождается перебалансировкой tablet. Перед запуском прогрева дождитесь завершения переноса, чтобы прогрев был эффективным. Определить, завершён ли перенос, можно по метрике FE doris_fe_tablet_num. Ровная стабильная кривая без колебаний означает, что перенос завершён и можно запускать прогрев.


Часто задаваемые вопросы​

Вопрос: доля попаданий в кэш низкая, а производительность запросов не улучшилась. Как найти причину?

  • Проверьте, достаточно ли свободного места на диске файлового кэша. Рекомендуемая ёмкость кэша должна как минимум в 1.5 раза превышать объём горячих данных.
  • Проверьте, не приводят ли крупные запросы к частому вытеснению горячих данных. Рассмотрите возможность изоляции крупных запросов.
  • Низкая доля попаданий в течение короткого периода после перезапуска — нормальное явление: восстановление LRU требует времени. Можно заранее выполнить ручной прогрев.

Вопрос: после добавления узлов запросы не находят данные в кэше. Что делать?

  • Убедитесь, что перебалансировка tablet завершена (кривая doris_fe_tablet_num ровная и стабильная).
  • Выполните команду ручного прогрева для целевых таблиц и разделов.
  • После горизонтального масштабирования с добавлением узлов скачивание данных на новые узлы BE занимает время. Промахи кэша в этот период ожидаемы. Явное включение чтения из кэша других узлов сокращает влияние этого временного интервала; проверьте, включён ли этот механизм.

Вопрос: приводит ли Base Compaction к вытеснению горячих данных?

  • По умолчанию Base Compaction записывает данные в кэш только при наличии достаточного свободного места и не вытесняет горячие данные принудительно.
  • Если включён параметр enable_file_cache_keep_base_compaction_output = true, данные Base Compaction принудительно записываются в кэш, что может привести к вытеснению горячих данных. Оцените этот компромисс с учётом фактической нагрузки.

Вопрос: удаляются ли данные сразу после истечения TTL?

  • Нет, данные удаляются не сразу. После истечения TTL они переводятся в тип Normal и помещаются в очередь Normal, где участвуют в обычном вытеснении LRU. Окончательный момент удаления данных определяется механизмом вытеснения.

Вопрос: позволяет ли ручной прогрев избежать повторного скачивания данных, уже находящихся в кэше?

  • Да. При прогреве Doris автоматически определяет данные, уже находящиеся в кэше, и выполняет инкрементальное скачивание только новых или изменённых данных.