Технический справочник pg_local_cache

Технический справочник по конечной точке RESP2, согласованности кэша, ограничениям ресурсов и безопасности. Инструкции по настройке см. в кратком руководстве и руководстве по установке.

Поддерживаемые таблицы и ключи

Подключайте постоянные heap-таблицы с действительным первичным ключом. Секционированные таблицы, таблицы с наследованием, защитой на уровне строк (RLS), временные и внешние таблицы, а также таблицы, принадлежащие расширениям, не поддерживаются. Поддерживаются следующие типы первичного ключа: smallint, integer, bigint, text, varchar, char с детерминированными сортировками и uuid. Составные ключи могут использовать эти типы; число столбцов не должно превышать 16.

Изменения DDL требуют сверки сопоставлений. См. руководство по установке.

Путь чтения и безопасный обход

Путь чтения RESP MGET: попадание в кэш, заполнение из источника с барьером и обход через аварийный выключатель.

Перед поиском каждый ключ RESP MGET проверяется и приводится к каноническому виду. При попадании в кэш возвращается JSON всей строки. При промахе воркер читает исходную таблицу в короткой транзакции и публикует результат в кэше, только если барьер чтения всё ещё действителен. Для отсутствующих строк возвращается nil. Строки, полезная нагрузка которых не помещается в общий кэш, всё равно могут быть возвращены из PostgreSQL, если их JSON укладывается в лимит значения RESP.

Попадание использует быстрый путь без аллокаций только при одном ключе в запросе и таблице с одноколоночным первичным ключом типа поддерживаемого целого числа, text или varchar без ограничения длины, без ограничения typmod, и с JSON ключа, поддерживаемым сканером. Для текстового ключа требуется кодировка базы UTF-8; целочисленные ключи поддерживаются и при других кодировках. Остальные формы ключей, запросы с несколькими ключами и неподдерживаемые состояния кэша используют общий путь.

Отложенные промахи и сроки блокировок

Перед SPI worker без ожидания пытается получить AccessShareLock исходного отношения. Если блокировка занята, он освобождает claim, прерывает транзакцию и помещает запрос в очередь worker: не более pg_local_cache.max_deferred_misses (по умолчанию 8) и 512 КиБ байтов на worker. У клиента может быть только один отложенный запрос. Если очередь заполнена, возвращается -ERR busy: relation locked, retry в порядке ответа. Последующие команды этого клиента ждут, остальные клиенты worker продолжают работу. Повторный запрос проверяет поколение mapping и учитывает оставшийся statement_timeout; при истечении возвращается -ERR MGET deadline exceeded. Это покрывает только исходную блокировку отношения. RESP STAT показывает worker-счётчики deferred_misses_total, deferred_misses_current, deferred_timeouts_total и deferred_rejections_total.

Согласованность транзакций

Инвалидация при записи: барьеры до фиксации защищают зафиксированные записи; откат до публикации барьера сохраняет прежние записи действительными.

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

Для чтения по RESP используется pg_local_cache.role; такие чтения выполняются в коротких транзакциях вне SQL-транзакции клиента.

Кэш, индексы, markers и арены защищены независимыми секционными блокировками. При записи сначала собираются дедуплицированные ключи; keyed fence защищает имеющуюся запись, а marker защищает ключ без записи и не допускает fill, пока его удерживает writer. При исчерпании marker или лимита транзакционных ключей fence расширяется на отношение, а при недоступном состоянии отношения — глобально. Это generation fence, а не единая глобальная блокировка кэша.

Общая память и конфигурация

При запуске PostgreSQL расширение заранее выделяет ограниченную общую память для кэша, сопоставлений и состояния воркеров и клиентов. memory_budget_mb ограничивает детерминированное выделение памяти расширением. Отказ в допуске или вытеснение записей не приводят к превышению настроенной ёмкости; чтение в таких случаях выполняется из PostgreSQL.

cache_entries считает дескрипторы, не фиксированные слоты строк. Ключи и JSON размещаются в локальной арене каждой секции: страницы 64 КиБ назначаются по запросу блокам 256 байт–16 КиБ. При нехватке блока строка возвращается из PostgreSQL без помещения в кэш. lock_partitions по умолчанию равен 64, принимает степени двойки 16–256; малый кэш автоматически уменьшает число секций, стремясь к 32 дескрипторам на секцию, но число секций не опускается ниже 16. Маркеры автоматически ограничены min(16384, max(1024, floor(cache_entries / 4))) записями и min(16, max(1, floor(memory_budget_mb / 25))) МиБ памяти ключей; -1 включает авторасчёт. Встроенный cache_entries по умолчанию — 262144, рассчитано для стандартных 384 МиБ с резервом не менее половины под арену; диапазон 128–16777216. При достаточной памяти и малом размере строк возможны миллионы ключей. Все компоненты входят в проверку бюджета.

Мягкий RLIMIT_NOFILE каждого RESP worker должен быть не ниже min(max_clients, max_clients_per_worker) + 33; увеличьте nofile процесса/контейнера при росте клиентских слотов.

Параметр По умолчанию Диапазон Применение
pg_local_cache.enabled on on / off SIGHUP
pg_local_cache.allow_plaintext_network off on / off Перезапуск
pg_local_cache.tls off on / off Перезапуск
pg_local_cache.tls_cert_file пусто путь к PEM-файлу Перезапуск
pg_local_cache.tls_key_file пусто путь к PEM-файлу Перезапуск
pg_local_cache.tls_ca_file пусто путь к CA PEM-файлу Перезапуск
pg_local_cache.tls_min_protocol_version TLSv1.2 TLSv1.2 / TLSv1.3 Перезапуск
pg_local_cache.port 6380 0–65535; 0 отключает RESP Перезапуск
pg_local_cache.workers 4 1–32 Перезапуск
pg_local_cache.cache_entries 262144 128–16777216 Перезапуск
pg_local_cache.dirty_marker_entries -1 -1 или 128–1048576 Перезапуск
pg_local_cache.dirty_marker_memory_mb -1 -1 или 1–1024 МиБ Перезапуск
pg_local_cache.lock_partitions 64 степень двойки 16–256; малый кэш использует меньше Перезапуск
pg_local_cache.relation_states 1024 128–8192 Перезапуск
pg_local_cache.max_clients 256 1–4096; не больше числа слотов воркеров Перезапуск
pg_local_cache.max_clients_per_worker 64 1–4096 Перезапуск
pg_local_cache.memory_budget_mb 384 64–8192 МБ Перезапуск
pg_local_cache.idle_timeout_ms 300000 1000–86400000 Перезапуск
pg_local_cache.statement_timeout_ms 2000 100–60000 Перезапуск
pg_local_cache.lock_timeout_ms 250 10–60000 Перезапуск
pg_local_cache.singleflight_wait_ms 25 0–1000 Перезапуск
pg_local_cache.max_deferred_misses 8 1–64 per worker Перезапуск
pg_local_cache.max_pipeline_commands 256 1–4096 Перезапуск
pg_local_cache.max_dirty_keys 4096 128–16384 Перезапуск
pg_local_cache.bind_address 127.0.0.1 IPv4-адрес Перезапуск
pg_local_cache.database postgres имя базы данных Перезапуск
pg_local_cache.role local_cache_worker роль PostgreSQL с атрибутом LOGIN Перезапуск
pg_local_cache.auth_token_file пусто файл принадлежит системному пользователю PostgreSQL, режим 0400 или 0600 Перезапуск
pg_local_cache.auth_token пусто встроенный токен; только для разработки Перезапуск
pg_local_cache.allow_superuser off on / off; только для разработки Перезапуск

Все параметры, кроме enabled, относятся к postmaster и требуют перезапуска. Число клиентских слотов должно удовлетворять условию max_clients <= workers × max_clients_per_worker.

Конечная точка RESP2

Конечная точка принимает RESP2. Ключи имеют вид CRUD:<db>.<schema>.<table>:<json pk>. MGET сохраняет порядок запросов и дубликаты; для отсутствующей строки возвращается элемент nil. Один запрос может содержать не более 1 024 ключей; размер каждой JSON-строки ограничен 65 536 байтами, а кодированного ответа — 66 560 байтами.

Поддерживаются команды работы с данными MGET, SET и DEL; требуется AUTH. Также поддерживаются PING, ECHO, INFO, STAT/STATS, ограниченная по области действия команда INVALIDATE, HELLO 2, QUIT, CLIENT SETINFO/SETNAME/GETNAME/ID, COMMAND и SELECT 0. Неподдерживаемые команды возвращают ошибку. RESP-клиенты используют базу данных 0; база данных и таблица определяются каждым ключом кэша.

TLS и модель безопасности

По умолчанию listener привязан к IPv4 loopback. Для TLS в RESP используются отдельные параметры расширения, а не параметры PostgreSQL ssl_*. Нужны сборка PostgreSQL с поддержкой OpenSSL, серверные сертификат и ключ в формате PEM, а также перезапуск. Параметр tls_ca_file включает обязательную проверку сертификатов клиентов (mTLS); минимальная версия TLS по умолчанию — 1.2.

Если TLS отключён, для plaintext-подключений вне loopback требуется allow_plaintext_network=on и доверенная сеть. Listener вне loopback требует токен длиной не менее 32 байт. Рекомендуется хранить токен в файле с ограниченными правами доступа. Все RESP-клиенты используют одну настроенную роль PostgreSQL с атрибутом LOGIN; права PostgreSQL не проверяются отдельно для каждого сетевого клиента. По умолчанию воркеры не работают от имени суперпользователя; такой режим предназначен только для разработки.

Аварийное отключение кэша

pg_local_cache.enabled — аварийный выключатель кэша с применением через SIGHUP. Когда параметр отключён, чтения RESP обходят общий кэш и выполняются по исходным таблицам; SET и DEL по-прежнему записывают данные через PostgreSQL. Воркеры применяют перезагрузку асинхронно, на границах команд. local_cache.health() сообщает значение параметра для вызвавшего функцию SQL-сеанса, а не подтверждение от всех воркеров. Перед возобновлением чтения из кэша после повторного включения увеличивается эпоха кэша.

Метрики и состояние

local_cache.health() сообщает о готовности, состоянии кэша и согласованности сопоставлений. local_cache.stats() возвращает счётчики в JSON, а local_cache.metrics() — типизированную строку метрик для экспортёра.

Метрики включают попадания и промахи кэша, отрицательные попадания; чтения из источника и записи; инвалидации и вытеснения; лидеров и ожидающих в single-flight, повторное использование результатов и тайм-ауты; активных и максимальное число клиентов; отклонения из-за лимита подключений; ошибки аутентификации и протокола; обратное давление при отправке данных и отключения медленных клиентов; запуски воркеров; обход из-за изменённых ключей; сбои и повторы загрузки сопоставлений; TLS-handshake и ошибки TLS-handshake. Измеряемые уровни включают ёмкость записей и отношений, число клиентов и воркеров, согласованность сопоставлений, объём общей памяти, памяти воркеров и расчётный объём памяти, а также настроенный бюджет.

Новые поля stats() включают fast_path_hits, fast_path_fallbacks и счётчики причин; cache_memory_capacity_bytes, cache_memory_used_bytes, cache_fragmentation_bytes, arena_admission_rejections_total; ёмкость, использование, максимум и fallback markers, а также эффективные лимиты markers.

Далее: краткое руководство, установка и обновление.