Cache-aside для PostgreSQL и Redis
При cache-aside для Redis приложение находится между чтением и авторитетным хранилищем. При промахе оно читает PostgreSQL, возвращает значение и записывает его в Redis; при записи обновляет PostgreSQL и инвалидирует соответствующий ключ Redis. В руководстве по паттерну Redis описан этот поток, но он не делает кэш приложения транзакционно согласованным с PostgreSQL.
Для строки с ключом public.items.id схема выглядит так:
GET item:42
miss -> SELECT * FROM public.items WHERE id = $1
-> SET item:42 <serialized row> EX <ttl>
write -> UPDATE public.items ...
-> COMMIT
-> DEL item:42
Используйте параметризованный SQL и пространство имён ключей. TTL ограничивает время, в течение которого сохранённое значение остаётся в Redis; он не доказывает свежесть относительно коммита PostgreSQL. Явное удаление обрабатывает обычные записи, но не устраняет каждую гонку.
Гонка инвалидации
Рассмотрим два запроса. Читатель R1 не находит ключ в Redis и читает старую
строку из PostgreSQL. Записывающий сеанс W фиксирует новую строку и удаляет
item:42. Затем R1 продолжает работу и сохраняет старое значение в Redis.
Следующий читатель видит устаревшие данные, пока этот ключ не истечёт или другая
запись его не удалит.
Возможные меры включают повторное удаление после завершения загрузчика, хранение версии базы данных и отклонение старых значений, сериализацию загрузок по ключу или публикацию зафиксированных изменений через outbox либо потребитель CDC. Каждая мера добавляет координацию и новые случаи отказа. В руководстве по инвалидации кэша показана аналогичная проблема позднего заполнения внутри PostgreSQL.
Где находится pg_local_cache
pg_local_cache — более узкий вариант внутри PostgreSQL для целых строк,
адресуемых первичным ключом. local_cache.mget вызывается явно; обычный SELECT
и произвольная форма запроса не читают кэш. Триггеры подключённых таблиц
ограждают затронутые ключи или отношения на пути записи в базу, а подходящие
чтения могут перейти к PostgreSQL, если правила транзакций или снимка запрещают
попадание в кэш. Начните с руководства по пакетному чтению
и технического контракта.
Это расширение не обеспечивает общую совместимость с Redis, TTL Redis или распределённый протокол кэша приложения. Его необязательная конечная точка RESP2 предоставляет ограниченный аутентифицированный набор команд через те же сопоставления и имеет собственную модель безопасности; TLS отсутствует. Используйте её, когда проблема — транзакционно согласованные чтения целых строк внутри PostgreSQL. Используйте Redis, когда нескольким экземплярам приложения нужны общие объекты, свежесть по TTL или структуры данных Redis. При совместном использовании нужны отдельные ключи, инвалидация и метрики для каждого слоя.
Запустите quickstart, сравните с обычным запросом клиента в примере node-postgres и изучите отдельные счётчики SQL и RESP. В руководстве по выбору кэширования перечислены другие варианты PostgreSQL.
Обновлено .