Что такое механизм NOTIFY/LISTEN в PostgreSQL и для чего он используется в бэкенде?

Ответ

NOTIFY и LISTEN в PostgreSQL — это асинхронный механизм межпроцессного взаимодействия, который позволяет реализовать паттерн "Издатель-подписчик" (Pub/Sub) на уровне базы данных.

Принцип работы:

  1. Подписчик (LISTEN): Один или несколько клиентов (сессий) подписываются на канал, выполняя команду LISTEN channel_name;.
  2. Издатель (NOTIFY): Другой клиент отправляет уведомление в этот канал с помощью команды NOTIFY channel_name, 'payload';. Полезная нагрузка (payload) — это опциональная строка.
  3. Получение уведомления: Все подписчики асинхронно получают уведомление. Это не прерывает их текущие запросы.

Основные сценарии использования в бэкенде:

  • Real-time обновления: Отправка сигналов веб-серверу (например, через WebSocket) об изменении данных для немедленного обновления UI у клиентов.
  • Инвалидация кэша: При изменении данных в таблице можно отправить NOTIFY, чтобы сервисы, кэширующие эти данные, сбросили свой кэш.
  • Сигнализация для фоновых воркеров: Основное приложение может уведомить фоновый воркер о появлении новой задачи в очереди без необходимости постоянно опрашивать БД (polling).

Пример использования в Go (с библиотекой pgx):

// Воркер, который слушает уведомления
go func() {
    conn, _ := pgx.Connect(context.Background(), os.Getenv("DATABASE_URL"))
    defer conn.Close(context.Background())

    _, err := conn.Exec(context.Background(), "listen updates")
    if err != nil { /* ... */ }

    for {
        notification, err := conn.WaitForNotification(context.Background())
        if err != nil { /* ... */ }
        fmt.Printf("PID: %d, Channel: %s, Payload: %sn", 
            notification.PID, notification.Channel, notification.Payload)
    }
}()

// ... в другой части приложения, например, в HTTP-обработчике

// conn2 - другое соединение
_, err := conn2.Exec(context.Background(), "notify updates, 'user 123 updated' ")

Особенности и ограничения:

  • Транзакционность: Уведомления отправляются только после успешного коммита транзакции, в которой был выполнен NOTIFY.
  • Нет гарантии доставки: Если клиент отключается, он теряет все уведомления, отправленные во время его отсутствия.
  • Ограниченный размер payload: Полезная нагрузка не может превышать 8000 байт.