Postgres Listen / Notify As Message Queue

17

Existe-t-il un moyen d'utiliser la fonction Postgres Listen / Notify pour envoyer un message à un canal et qu'un seul auditeur consomme ce message?

Le but de ceci est que j'ai plusieurs applications «ouvrières» écoutant toutes le même canal Postgres. Mais je ne veux que le travail soit effectué une fois par message reçu via le canal de notification.

Si Listen / Notify n'est pas la fonctionnalité correcte dans Postgres, y a-t-il une fonctionnalité distincte que je devrais utiliser?

Idéalement, je voudrais le faire sans utiliser d'extensions supplémentaires.

moesef
la source

Réponses:

23

Selon la documentation de PostgreSQL surNOTIFY :

La commande NOTIFY envoie un événement de notification avec une chaîne facultative de "charge utile" à chaque application client qui a précédemment exécuté le canal LISTEN pour le nom de canal spécifié dans la base de données actuelle. Les notifications sont visibles par tous les utilisateurs .

(c'est moi qui souligne)

Cela signifie que vous ne pouvez pas faire ce que vous voulez juste avec LISTEN/NOTIFY . Cependant, vous pouvez avoir à la fois une table pour stocker les messages en file d'attente, LISTEN/NOTIFYpour avertir les applications externes qu '«il y a de nouvelles choses dans la file d'attente des messages» et utiliser une logique supplémentaire de ces applications externes pour qu'une seule personne consomme le message.

La stratégie décrite dans l'article À quoi sert SKIP LOCKED dans PostgreSQL 9.5? est probablement le moyen le plus sûr / le plus simple d'implémenter une file d'attente de messages dans PostgreSQL. Portez une attention particulière à la partie «Comment SKIP LOCKED aide». Lisez également attentivement l'une de leurs mises en garde:

Une file d'attente implémentée dans le SGBDR ne correspondra jamais aux performances d'un système de file d'attente dédié rapide, même celui qui offre les mêmes garanties d'atomicité et de durabilité que PostgreSQL. L'utilisation de SKIP LOCKED est meilleure que les approches existantes dans la base de données, mais vous irez toujours plus vite en utilisant un moteur de mise en file d'attente externe dédié et hautement optimisé.

Ceci est particulièrement important si le volume de la file d'attente est élevé.

joanolo
la source
1
Je souhaite pouvoir attribuer une prime à l'auteur de cet article. Tellement extrêmement utile.
Wildcard
3

J'ai fait quelque chose comme ça il y a quelque temps avec un bon succès, j'ai utilisé RabbitMQ et ce plugin https://github.com/gmr/pgsql-listen-exchange

Fondamentalement, RabbitMQ se connecte à PostgreSQL et écoute l'événement de notification, alors vous pouvez utiliser RabbitMQ pour agréger ce message à autant de files d'attente que nécessaire et avoir une application consommant chaque file d'attente

Phill Pafford
la source