Управление памятью кэша внешних метаданных
Начиная с Doris 4.1.4, для некоторых кэшей внешних метаданных можно устанавливать ограничения на основе оценки объёма удерживаемой памяти. Это не позволяет метаданным большой таблицы, одного Catalog или нескольких Catalog непрерывно увеличивать потребление памяти в куче FE.
Используйте эту возможность, когда:
- В таблицах Hive достаточно много партиций, чтобы структуры для их отсечения занимали большой объём памяти.
- Метаданные таблиц, снимки или манифесты Iceberg имеют большой размер.
- Поколения таблиц или снимки Paimon содержат большой объём удерживаемых метаданных и проекций партиций.
- Один FE обслуживает несколько Catalog и нужно не допустить, чтобы один Catalog занимал основную часть памяти кэша метаданных.
Эти ограничения распространяются только на перечисленные в этом документе элементы кэша с поддержкой оценки памяти. Они не являются жёстким ограничением размера кучи FE. Общая инфраструктура среды выполнения, например клиенты Catalog и пулы потоков, не полностью относится к отдельному элементу кэша. При этом ограниченные по объёму данные конкретного владельца, удерживаемые элементом, включая контекст аутентификации и конфигурацию или учётные данные Iceberg FileIO, учитываются с запасом. На кэши метаданных без поддержки оценки памяти эта квота не распространяется.
Быстрый старт
Предварительные требования:
- Существующий Catalog Hive, Iceberg или Paimon.
- Разрешение на изменение конфигурации FE и целевого Catalog.
- Doris 4.1.4 или более поздней версии на каждом FE.
1. Настройте общий лимит FE
Задайте следующий параметр в fe.conf на каждом FE:
external_meta_cache_max_weight = 10%
После этого все управляемые кэши внешних метаданных на данном FE смогут суммарно использовать не более 10% максимального размера кучи JVM. Перезапустите FE после изменения этого параметра.
Можно также задать фиксированный размер:
external_meta_cache_max_weight = 8GB
2. Ограничьте один Catalog
В следующем примере суммарный объём управляемых кэшей метаданных в iceberg_ctl ограничивается 4 GB:
ALTER CATALOG iceberg_ctl SET PROPERTIES (
"meta.cache.max-weight" = "4GB"
);
После изменения Doris очищает инициализированную группу кэшей этого Catalog и при следующем обращении создаёт её заново с новой конфигурацией.
meta.cache.max-weight действует, даже если общий лимит FE не настроен. В этом случае он ограничивает только данный Catalog и не ограничивает суммарное потребление всех Catalog на FE.
3. Ограничьте отдельные элементы кэша
В следующем примере задаются лимит Catalog и лимиты отдельных элементов Iceberg:
ALTER CATALOG iceberg_ctl SET PROPERTIES (
"meta.cache.max-weight" = "4GB",
"meta.cache.iceberg.table.max-weight" = "1GB",
"meta.cache.iceberg.snapshot.max-weight" = "2GB",
"meta.cache.iceberg.manifest.enable" = "true",
"meta.cache.iceberg.manifest.max-weight" = "1GB"
);
Для элементов table, snapshot и manifest установлены ограничения 1 GB, 2 GB и 1 GB соответственно. Их суммарное потребление не может превышать лимит Catalog в 4 GB, а на сам Catalog по-прежнему распространяется общий лимит FE.
Иерархия квот
Доступны три уровня ограничения памяти:
| Уровень | Место настройки | Параметр | Формат | По умолчанию | Область действия |
|---|---|---|---|---|---|
| FE | fe.conf | external_meta_cache_max_weight | Фиксированный размер или процент от максимального размера кучи JVM | Не задан (0); общая квота FE отсутствует | Все управляемые кэши внешних метаданных на текущем FE |
| Catalog | Свойство Catalog | meta.cache.max-weight | Фиксированный размер; должен быть положительным | Не задан; квота Catalog отсутствует | Все управляемые элементы в текущем Catalog |
| Элемент кэша | Свойство Catalog | meta.cache.<engine>.<entry>.max-weight | Фиксированный размер; 0 отключает элемент | Не задан; ограничивается только лимитами родительских уровней | Один элемент кэша для одного движка |
Действующий лимит равен наименьшему из всех настроенных лимитов.
| Лимит FE | Лимит Catalog | Лимит элемента | Поведение |
|---|---|---|---|
| Не задан | Не задан | Не задан | Учёт памяти отключён; продолжают действовать существующие ограничения по числу записей и политики TTL |
| Задан | Не задан | Не задан | Все управляемые элементы совместно используют квоту FE |
| Не задан | Задан | Не задан | Управляемые элементы Catalog совместно используют квоту Catalog |
| Не задан | Не задан | Задан | Ограничивается только этот элемент; суммарный лимит FE или Catalog отсутствует |
| Задан | Задан | Задан | Действуют все три уровня; применяется самый строгий лимит |
Настроенная иерархия должна соответствовать следующим правилам:
- Лимит Catalog не может превышать общий лимит FE.
- Лимит элемента не может превышать настроенный лимит его непосредственного родительского уровня.
- Если FE имеют разные характеристики, ведомый FE дополнительно ограничивает приём данных в кэш своим локальным лимитом FE.
При недопустимой иерархии CREATE CATALOG или ALTER CATALOG завершается с ошибкой, а не молча игнорирует свойство.
Формат значений
Для фиксированных размеров поддерживаются следующие двоичные единицы измерения без учёта регистра:
B, KB, MB, GB, TB, PB
Примеры: 512MB и 4GB.
В значениях фиксированного размера необходимо использовать целое число. Дробные значения поддерживаются только для процентов, например 12.5%.
Только external_meta_cache_max_weight принимает процентные значения, например 10% или 12.5%. Процент рассчитывается от максимального размера кучи JVM каждого FE, поэтому FE с разными размерами кучи получают разные лимиты в байтах.
Ноль имеет разное значение на разных уровнях:
| Параметр | Значение 0 |
|---|---|
external_meta_cache_max_weight | Отключает общую квоту FE, не отключая кэши |
meta.cache.max-weight | Недопустимо; лимит Catalog должен быть положительным |
meta.cache.<engine>.<entry>.max-weight | Отключает этот элемент кэша; не отменяет переопределение на уровне элемента |
0% недопустимо. Чтобы отключить общую квоту FE, используйте обычное значение 0.
Поддерживаемые элементы кэша
В этой версии только следующие элементы принимают max-weight:
| Catalog/движок | Элемент | Свойство | Кэшируемые данные |
|---|---|---|---|
| Hive | partition_values | meta.cache.hive.partition_values.max-weight | Имена и значения партиций, индексы для отсечения партиций и отсортированные диапазоны |
| Iceberg | table | meta.cache.iceberg.table.max-weight | Метаданные таблицы Iceberg и поколение метаданных, удерживаемое в памяти |
| Iceberg | snapshot | meta.cache.iceberg.snapshot.max-weight | Снимок, проекция партиций и связанное с ней поколение таблицы, удерживаемое в памяти |
| Iceberg | manifest | meta.cache.iceberg.manifest.max-weight | Разобранные списки DataFile и DeleteFile; этот элемент по умолчанию отключён и также требует enable=true |
| Paimon | table | meta.cache.paimon.table.max-weight | Метаданные таблицы Paimon, удерживаемые в памяти, и её поколение |
| Paimon | snapshot | meta.cache.paimon.snapshot.max-weight | Снимок, поколение схемы и проекция партиций |
Следующие распространённые элементы по-прежнему ограничиваются по числу записей и не принимают max-weight:
- Hive
schema,partitionиfile. - Iceberg
schemaиview. - Paimon
schema. - Существующие элементы кэша Catalog Hudi, MaxCompute и Doris.
Установка max-weight для неподдерживаемого элемента приводит к ошибке создания или изменения Catalog. Например, следующая конфигурация недопустима:
ALTER CATALOG hive_ctl SET PROPERTIES (
"meta.cache.hive.file.max-weight" = "1GB"
);
Catalog HMS может направлять обращения к кэшам метаданных Hive, Hudi и Iceberg. Если он содержит таблицы Iceberg, в этом же Catalog HMS можно использовать meta.cache.iceberg.table.max-weight, meta.cache.iceberg.snapshot.max-weight и meta.cache.iceberg.manifest.max-weight.
Примеры
Использование только лимитов Catalog
Если общий лимит FE не задан, изолируйте Catalog независимо друг от друга:
ALTER CATALOG hive_prod SET PROPERTIES (
"meta.cache.max-weight" = "6GB"
);
ALTER CATALOG iceberg_ad_hoc SET PROPERTIES (
"meta.cache.max-weight" = "2GB"
);
Для этих Catalog установлены ограничения 6 GB и 2 GB соответственно, но общего ограничения на их суммарное потребление на FE нет.
Ограничение больших структур партиций Hive
ALTER CATALOG hive_ctl SET PROPERTIES (
"meta.cache.max-weight" = "4GB",
"meta.cache.hive.partition_values.max-weight" = "3GB"
);
Это прежде всего ограничивает структуры отсечения партиций, создаваемые для таблиц Hive с большим числом партиций. Кэши списков файлов Hive в эту квоту не входят.
Ограничение поколений таблиц и снимков Paimon
ALTER CATALOG paimon_ctl SET PROPERTIES (
"meta.cache.max-weight" = "2GB",
"meta.cache.paimon.table.max-weight" = "512MB",
"meta.cache.paimon.snapshot.max-weight" = "1536MB"
);
Paimon поддерживает независимые лимиты памяти для элементов table и snapshot. В этом примере для удерживаемых поколений таблиц выделяется до 512 MB, а для проекций снимков до 1536 MB в пределах лимита Catalog в 2 GB.
Совместимость с существующими свойствами кэша
Для совместимости с существующими Catalog значения table.enable, table.ttl-second и table.capacity для Iceberg и Paimon также используются как значения по умолчанию для соответствующего элемента снимков, если его свойство не задано явно. Например:
ALTER CATALOG paimon_ctl SET PROPERTIES (
"meta.cache.paimon.table.ttl-second" = "600",
"meta.cache.paimon.snapshot.max-weight" = "1536MB"
);
Здесь table.ttl-second управляет TTL как кэша объектов таблиц Paimon, так и кэша снимков, а snapshot.max-weight ограничивает только кэш снимков.
max-weight не участвует в таком сопоставлении для совместимости. Используйте фактическое имя элемента с поддержкой оценки памяти:
meta.cache.iceberg.table.max-weightдля объектов таблиц Iceberg.meta.cache.iceberg.snapshot.max-weightдля снимков Iceberg.meta.cache.paimon.table.max-weightдля поколений таблиц Paimon.meta.cache.paimon.snapshot.max-weightдля снимков Paimon.
Совместное использование лимитов памяти и политик TTL
Лимиты памяти можно использовать вместе с enable, ttl-second и capacity:
ALTER CATALOG iceberg_ctl SET PROPERTIES (
"meta.cache.iceberg.snapshot.enable" = "true",
"meta.cache.iceberg.snapshot.ttl-second" = "1800",
"meta.cache.iceberg.snapshot.capacity" = "1000",
"meta.cache.iceberg.snapshot.max-weight" = "2GB"
);
Когда max-weight активен, вытеснение ограничивается объёмом памяти, а capacity больше не задаёт одновременно действующий максимум числа записей. При этом capacity=0 по-прежнему отключает кэш, поэтому при использовании лимита памяти оставляйте это значение больше нуля.
Поведение при достижении лимита
При промахе кэша Doris:
- Загружает метаданные из внешнего источника.
- Фиксирует или материализует объект-кандидат и оценивает объём удерживаемой им памяти.
- Атомарно проверяет квоты FE, Catalog и элемента.
- Вытесняет редко используемые данные из того же элемента и повторяет проверку, если квоты недостаточно; если локальное вытеснение не позволяет зарезервировать необходимую память, Doris планирует освобождение памяти в соседних элементах (а при нехватке в рамках общей квоты FE также в других Catalog).
- Возвращает загруженный объект текущему запросу без сохранения в кэше, если приём в кэш по-прежнему невозможен.
Поэтому новый объект, размер которого превышает доступную квоту, обычно не приводит к сбою запроса из-за квоты кэша. Объект не удерживается в памяти, поэтому последующие обращения могут загружать его заново и увеличивать задержку планирования запросов.
Если Doris не может получить надёжную полную оценку, например из-за неподдерживаемого представления таблицы в памяти, ещё не выполненной отложенной загрузки метаданных Iceberg, ошибки подготовки или превышения лимита затрат на учёт, он также пропускает кэширование, чтобы не занижать объём объекта. Средства оценки не выполняют универсальный обход графа объектов с помощью рефлексии и не оценивают контейнеры по выборке. Iceberg использует единственную проверку приватного поля с отказом от кэширования при неудаче только для подтверждения того, что метаданные снимка уже загружены, чтобы избежать операций IO во время оценки.
Локальное вытеснение выполняется синхронно. Освобождение памяти в соседних элементах выполняется асинхронно и без гарантии результата, поэтому при текущем промахе объект всё ещё может быть возвращён без кэширования, пока в соседних элементах освобождается память для последующих приёмов в кэш. Настройте лимиты на уровне элементов, если один элемент не должен занимать основную часть общей квоты FE или Catalog.
Если запланированное обновление не может быть принято в кэш из-за неполной оценки или недостаточного бюджета, Doris сохраняет предыдущее заведомо корректное поколение в кэше. Отклонённый результат обновления не публикуется.
Проверки квот выполняются при приёме в кэш, после загрузки и подготовки объекта. Doris не резервирует память в куче до обращения к внешнему источнику. Поэтому ошибка загрузки из внешнего источника или ситуация, когда один исключительно большой объект исчерпывает кучу FE ещё до завершения своего создания, всё ещё может привести к сбою текущего запроса. Эта возможность ограничивает память, удерживаемую после успешной загрузки; она не защищает от OOM при единичной загрузке метаданных.
Применение конфигурации и обновление кэшей
- Перезапустите FE после изменения
external_meta_cache_max_weight. - Изменение свойств Catalog, включая
meta.cache.max-weightилиmeta.cache.<engine>.<entry>.*, сбрасывает контекст выполнения Catalog и очищает инициализированные элементы всех движков кэша метаданных, к которым этот Catalog направляет обращения; при следующем обращении они создаются заново с новым контекстом и конфигурацией. - Уже выполняющиеся запросы могут продолжать работу с загруженными объектами, а последующие обращения используют новую конфигурацию.
Лимиты памяти определяют, будут ли объекты удерживаться в памяти. Они не изменяют внешние метаданные и не заменяют REFRESH CATALOG, TTL или синхронизацию событий метаданных.
Мониторинг и диагностика нехватки памяти
Системная таблица catalog_meta_cache_statistics содержит отдельную строку для каждой комбинации FE, Catalog, движка кэша метаданных и элемента кэша. Следующие столбцы описывают управление памятью:
| Столбец | Значение | Временная характеристика |
|---|---|---|
MAX_WEIGHT | Действующий лимит памяти элемента в байтах. -1 означает, что к элементу не применяется ни лимит FE, ни лимит Catalog, ни лимит элемента. | Конфигурация |
ESTIMATED_WEIGHT | Оценка объёма в байтах, в данный момент зарезервированного элементом. | Текущее значение на момент запроса |
WEIGHT_REJECT_COUNT | Число отказов в приёме в кэш из-за недостаточного бюджета или неполной оценки. | Накопленное значение для текущего экземпляра кэша |
LAST_WEIGHT_REJECT_REASON | Причина последнего отказа. | Последнее значение |
Накопительные счётчики начинают отсчёт с нуля при пересоздании группы кэшей после изменения свойств Catalog или перезапуска FE. Таблица не хранит историю, поэтому периодически считывайте её, если нужно отслеживать динамику. Строки с max_weight >= 0 соответствуют элементам с управлением памятью; сами лимиты задаются в fe.conf и свойствах Catalog.
Выполните следующие действия, если потребление памяти в куче FE велико и вы подозреваете, что причина в кэшах внешних метаданных.
1. Проверьте, создают ли управляемые кэши нагрузку на память
SELECT fe_host,
SUM(estimated_weight) AS estimated_weight,
SUM(weight_reject_count) AS weight_reject_count
FROM information_schema.catalog_meta_cache_statistics
WHERE max_weight >= 0
GROUP BY fe_host
ORDER BY fe_host;
Сравните суммарный зарезервированный объём с настроенным external_meta_cache_max_weight и с размером кучи FE. Это значение представляет собой оценку объёма памяти, удерживаемой кэшем, а не общий объём используемой кучи FE. Оно не включает временную память при загрузке, элементы с ограничением по числу записей и кэши SDK коннекторов. Если потребление памяти в куче FE остаётся высоким при небольшом зарезервированном объёме, перейдите к шагу 6.
2. Найдите Catalog, создающие нагрузку
SELECT fe_host, catalog_name,
SUM(estimated_weight) AS estimated_weight,
SUM(weight_reject_count) AS weight_reject_count
FROM information_schema.catalog_meta_cache_statistics
WHERE max_weight >= 0
GROUP BY fe_host, catalog_name
ORDER BY estimated_weight DESC;
Сравните каждый Catalog с его meta.cache.max-weight. Ищите Catalog, зарезервированный объём которого близок к лимиту или значительно больше на одном FE, чем на остальных.
3. Изучите отдельные элементы кэша
SELECT engine_name, entry_name,
estimated_weight, max_weight,
weight_reject_count, last_weight_reject_reason
FROM information_schema.catalog_meta_cache_statistics
WHERE fe_host = '<fe_host>'
AND catalog_name = '<catalog_name>'
AND max_weight >= 0
ORDER BY estimated_weight DESC;
Элемент, у которого estimated_weight приближается к max_weight, занимает основную часть памяти Catalog. Рост weight_reject_count указывает на нехватку квоты: объекты загружаются, редко используемые данные вытесняются, но объект всё равно не сохраняется в кэше, поэтому последующие обращения загружают его заново. last_weight_reject_reason показывает, был ли последний отказ вызван недостаточным бюджетом или неполной оценкой. Неполная оценка не является проблемой квоты; объект предоставляется запросу без кэширования.
4. Выберите способ управления
| Цель | Параметр | Когда вступает в силу |
|---|---|---|
| Ограничить суммарное потребление на одном FE | external_meta_cache_max_weight в fe.conf | После перезапуска FE |
| Изолировать один Catalog | meta.cache.max-weight | При следующем обращении после ALTER CATALOG |
| Не допустить преобладания одного поддерживаемого элемента | meta.cache.<engine>.<entry>.max-weight | При следующем обращении после ALTER CATALOG |
| Отдать предпочтение более свежим метаданным, а не кэшированию | Уменьшить meta.cache.<engine>.<entry>.ttl-second или установить meta.cache.<engine>.<entry>.enable в false | При следующем обращении после ALTER CATALOG |
5. Что происходит после изменения
- Изменение свойства Catalog очищает инициализированную группу кэшей этого Catalog и пересоздаёт её по мере обращений. Счётчики в системной таблице начинают отсчёт с нуля.
- Уже выполняющиеся запросы сохраняют свои загруженные объекты.
- Снижение квоты увеличивает число промахов. Ожидайте больше загрузок внешних метаданных и более высокую задержку планирования, пока рабочий набор снова не начнёт помещаться в квоту.
6. Какие проблемы этот механизм не решает
Если потребление памяти в куче FE остаётся высоким при небольшом учитываемом объёме, источник нагрузки находится за пределами квоты. Дальнейшее снижение max-weight не поможет. Вместо этого проверьте:
- Элементы с ограничением по числу записей, например Hive
schema,partitionиfile. Настройте ихcapacityиttl-second. - Объекты метаданных, на которые всё ещё ссылаются выполняющиеся запросы.
- Кэши SDK коннекторов, например кэш манифестов Iceberg, управляемый
io.manifest.cache-enabled, илиCachingCatalogPaimon, управляемыйpaimon.cache-enabled. - Пики потребления памяти при загрузке и материализации одного большого объекта метаданных, возникающие до приёма в кэш.
Справочник по симптомам
| Симптом | Запрос | Интерпретация | Действие |
|---|---|---|---|
Потребление памяти в куче FE высоко, а суммарный зарезервированный объём близок к external_meta_cache_max_weight | Шаг 1 | Управляемые кэши достигли общего лимита FE | Снизьте лимит FE или лимит самого большого Catalog либо увеличьте размер кучи FE |
| Потребление памяти в куче FE высоко, но суммарный зарезервированный объём мал | Шаг 1 | Источник нагрузки находится за пределами квоты | Выполните шаг 6 |
Один Catalog близок к своему meta.cache.max-weight или значительно больше на одном FE | Шаг 2 | Его рабочий набор превышает выделенную ему долю | Увеличьте его лимит, если позволяет размер кучи, или добавьте лимиты элементов внутри него |
weight_reject_count продолжает расти, а причиной является недостаточный бюджет | Шаг 3 | Объекты загружаются, но не удерживаются в памяти и впоследствии загружаются заново | Увеличьте квоту или уменьшите лимиты конкурирующих элементов |
weight_reject_count продолжает расти, а причиной является неполная оценка | Шаг 3 | Объект невозможно надёжно оценить, и он никогда не кэшируется | Изменение квот не поможет; запросы по-прежнему успешно выполняются без кэширования |
estimated_weight остаётся на уровне max_weight, а доля попаданий в кэш мала | Шаг 3 | В элементе постоянно происходит вытеснение и повторная загрузка в пределах его квоты | Увеличьте лимит элемента или сократите TTL, чтобы уменьшить рабочий набор |
Ограничения и особенности
max-weightпредставляет собой бюджет приёма в кэш на основе оценки удерживаемой памяти. Формулы для конкретных типов используют округлённые вверх структурные константы, откалиброванные заранее, а также счётчики объёма данных, собранные при загрузке; они не моделируют точную организацию памяти работающей JVM или стороннего SDK. Результат не равен RSS в операционной системе и не заменяет мониторинг кучи FE и GC.- Общая инфраструктура среды выполнения не полностью учитывается в расходах отдельного элемента, но ограниченные по объёму контекст аутентификации конкретного владельца, конфигурация FileIO, учётные данные хранилища и данные преобразований, удерживаемые элементом, учитываются с запасом.
- Элементы с ограничением по объёму памяти используют мягкие ссылки на значения. Записи резервирования сохраняют ключ, поколение и вес, но не содержат сильной ссылки на кэшированное значение. При нехватке памяти в куче JVM может удалить значение до истечения его TTL или заполнения квоты; Doris снимает соответствующее резервирование и загружает значение заново при последующем обращении.
- Большие объекты оцениваются только при загрузке, обновлении или замене. Итоговый вес хранится вместе с опубликованным поколением, поэтому попадания в кэш не вызывают повторного сканирования содержимого объектов.
- При первом приёме таблицы или снимка Iceberg в кэш могут материализоваться списки манифестов текущего снимка, что может увеличить задержку первоначальной загрузки.
- При задании новых свойств в DDL опечатки в именах движков, именах элементов и параметрах строго отклоняются; для ранее сохранённых свойств, которые невозможно разобрать во время выполнения, выдаётся предупреждение, и они игнорируются, чтобы Catalog после обновления всё ещё мог инициализироваться.
- Когда управление памятью Doris активно для Catalog Iceberg, кэш содержимого манифестов Iceberg SDK не включается автоматически, поскольку находится за пределами квоты Doris. Явно заданный параметр
io.manifest.cache-enabledимеет приоритет. - Когда управление памятью Doris активно для Catalog Paimon,
CachingCatalogна уровне SDK Paimon по умолчанию отключён, чтобы избежать второго неограниченного кэша метаданных. Явно заданный параметрpaimon.cache-enabledимеет приоритет. - После обновления Iceberg или Paimon используйте версию SDK, поставляемую в составе релиза Doris, вместо самостоятельной замены JAR-файлов SDK в FE.
Рекомендации
- Начните с общего лимита FE, чтобы суммарное потребление всех Catalog не могло расти без ограничений.
- Добавьте лимиты Catalog для крупных производственных Catalog, совместно использующих один FE.
- Добавляйте лимиты на уровне элементов только для тех элементов, которые занимают основную часть памяти; отдельная настройка нужна не каждому элементу.
- Резервируйте достаточно памяти в куче для планирования запросов и других кэшей FE, не отдавая большую часть кучи JVM кэшам внешних метаданных.
- Увеличьте квоту или уменьшите лимиты конкурирующих элементов, если один и тот же объект многократно загружается заново после отказа в приёме в кэш.
- Используйте процентное значение при разных размерах кучи FE или фиксированный размер, если на всех FE должен действовать одинаковый лимит в байтах.