А вам действительно нужен Redis, когда есть PostgreSQL?

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

Есть проверенная временем архитектура, которую я видел много раз для реализации веб-сервисов и приложений:
1. PostgreSQL для хранения реляционных данных
2. Redis для координации очередей фоновых заданий (и нескольких классических атомарных операций)

И Redis действительно прекрасен, но что если я скажу вам, что наиболее распространненые варианты его использования прекрасно покрываются функциональными возможностями PostgreSQL?

Пример использования №1: Очередь заданий
Возможно, самое частое использование Redis, которое я наблюдал - это выполнение задач в фоновом режиме. Идея состоит в том, чтобы выполнить какую-нибудь задачу в фоне (возможно с некоторыми входными данными) и гарантировать, что только один из воркеров выполнит его. Redis прекрасно справляется с этим, поскольку предоставляет богатый набор атомарных операций для своих структур данных.

Но с момента появления PostgreSQL 9.5 появилась SKIP LOCKED опция для SELECT ... FOR ... оператора (вот документация - https://www.postgresql.org/docs/9.5/sql-select.html#SQL-FOR-UPDATE-SHARE). Когда указывается данныая опция, PostgreSQL просто игнорирует любые строки, требующие ожидания для снятия блокировки.

Рассмотрим этот пример с точки зрения фонового работника:
BEGIN;
WITH job AS (
SELECT id
FROM jobs
WHERE status = 'pending'
LIMIT 1
FOR UPDATE SKIP LOCKED
)
UPDATE jobs SET status = 'running'
WHERE jobs.id = job.id
RETURNING jobs.*;
COMMIT;

При указании FOR UPDATE SKIP LOCKED, неявно устанавливается блокировка на уровне строк, возвращаемых из SELECT. Помимо того, поскольку вы указали SKIP LOCKED, нет шансов, что вы получите записи, заблокированные в другой транзкции (другим воркером). Не нужно беспокоиться о том, что несколько воркеров, выполняющих эту команду, получат одну и ту же строку из-за row-level блокировки.

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

Пример использования №2: Блокировки на уровне приложения
Представим типичную ситуацию, что у нас есть процедура синхронизации со сторонней служной и требуется, чтобы данная процедура не могла выполняться одновременно в разных процессах и\или на разных серверах. Это еще один распространенный кейс использования Redis - распределенные блокировки.

PostgreSQL также может помочь с этой задачей с помощью Advisory Locks (https://www.postgresql.org/docs/9.2/explicit-locking.html#ADVISORY-LOCKS). Данных механизм блокировок используется PostgreSQL для внутренних целей, но при этом имеется возможность использования данного механизма в своих приложениях.

Пример использования №3: Pub\Sub
Cамый крутой пример использования я оставил напоследок: отправка сообщений со стороны сервера и возможность подписаться на эти сообщения. Например, скажем, вам нужно уведомить пользователя о том, что у него есть новое сообщение. Или, возможно, вы хотите передать данные клиенту после их обработки в фоне, когда они становятся доступными. Обычно, веб-сокеты являются трансопртным уровнем для этих событий, а Redis - движком Pub\Sub.

Однако, начиная с 9-ой версии PostgreSQL также предоставляет эту функциональность с помощью операторов LISTEN и NOTIFY. Любой клиент PostgreSQL может подписаться (LISTEN) на конкретный канал сообщений, который представляет из себя просто строковое значение. Когда другой PostgreSQL клиент отправляет сообщение (NOTIFY) по этому каналу, все остальные подписанные клиенты будут уведомлены. По желанию можно прикрепить небольшое сообщение.

Если вы используйте Rails и ActionCable, использование PostgreSQL даже поддерживается из коробки (прим. автора: данная поддержка есть практически во всех популярных фреймворках (Django Celery, PHP Symfony Messenger, etc)).

Полные возможности использования PostgreSQL
Redis принципиально занимает другую нишу, чем PostgreSQL и прекрасно подходит во многих кейсах разработки программного обеспечения, куда PostgreSQL даже не стремится. Например, кэширование данных с TTL, а также хранение и управление эфемерными данными.

Однако, PostgreSQL имеет гораздо больше возможностей, чем вы зачастую ожидаете изначально, когда берете его только в качестве базы данных SQL для вашей любимой ORM.

И есть большая вероятность, что вещи, для которых вы тянете в проект Redis, могут оказаться по силам и вашему PostgreSQL. И возможно в каких то ситуациях стоит отказаться от Redis и сэкономить на эксплуатационных расходах и сложности разработки.

Источник: https://habr.com/ru/post/564230/


Интересные статьи

Интересные статьи

Есть проверенная архитектура, которую я видел много раз для поддержки ваших веб-сервисов и приложений: PostgreSQL для хранения данных Redis для координации очередей фоновых зада...
Если объяснять на пальцах, термоядерный реактор — это когда в магнитном поле удерживают плазму с температурой в 150 раз выше, чем на Солнце, а в трех метрах от нее находится охлаждающ...
Обсуждаем, почему устали зрители и что с этим можно сделать. Читать дальше →
Все уже привыкли к тому, что данные клиентов российских банков то тут, то там всплывают либо в открытом доступе, либо выставляются на продажу на различных теневых форумах. Сейчас хочется пого...
За последние два десятилетия не так часто появлялись CPU, которые можно назвать «революционными». Но компании AMD в ноябре 2019 года удалось сделать это. Первые тесты процессоров Ryzen Thread...