RabbitMQ – Ordine di consegna del messaggio

Devo scegliere un nuovo broker di code per il mio nuovo progetto.

Questa volta ho bisogno di una coda scalabile che supporti pub / sub, e mantenere l’ordine dei messaggi è un must.

Leggo il commento di Alexis: Scrive:

“In effetti, pensiamo che RabbitMQ fornisca ordini più forti di Kafka”

Ho letto la sezione relativa all’ordine dei messaggi nei documenti di rabbitmq:

“I messaggi possono essere restituiti alla coda usando i metodi AMQP che dispongono di un parametro requeue (basic.recover, basic.reject e basic.nack), oa causa della chiusura di un canale mentre si tengono messaggi non riconosciuti … Con la versione 2.7.0 e successive è ancora ansible per i singoli consumatori osservare i messaggi fuori servizio se la coda ha più abbonati, a causa delle azioni di altri abbonati che potrebbero riaccendere i messaggi. Dal punto di vista della coda i messaggi vengono sempre mantenuti nell’ordine di pubblicazione. ”

Se devo gestire i messaggi in base al loro ordine, posso usare solo rabbitMQ con una coda esclusiva per ciascun consumatore?

RabbitMQ è ancora considerato una buona soluzione per l’accodamento dei messaggi ordinato?

Bene, diamo uno sguardo più da vicino allo scenario che stai descrivendo sopra. Penso che sia importante incollare la documentazione immediatamente prima dello snippet nella domanda per fornire il contesto:

La sezione 4.7 della specifica di base AMQP 0-9-1 spiega le condizioni in base alle quali l’ordine è garantito: i messaggi pubblicati in un canale, passando attraverso uno scambio e una coda e un canale in uscita saranno ricevuti nello stesso ordine in cui sono stati inviati. RabbitMQ offre maggiori garanzie dalla versione 2.7.0.

I messaggi possono essere restituiti alla coda usando i metodi AMQP che dispongono di un parametro requeue (basic.recover, basic.reject e basic.nack), oppure a causa della chiusura di un canale mentre si tengono messaggi non confermati. Ognuno di questi scenari ha causato la riaccensione dei messaggi sul retro della coda per le versioni di RabbitMQ precedenti alla 2.7.0. Dalla versione 2.7.0 di RabbitMQ, i messaggi vengono sempre trattenuti in coda nell’ordine di pubblicazione, anche in presenza di riaccodamento o chiusura del canale. (enfasi aggiunta)

Quindi, è chiaro che RabbitMQ, dalla 2.7.0 in poi, sta facendo un miglioramento piuttosto drastico rispetto alle specifiche AMQP originali per quanto riguarda l’ordinamento dei messaggi.

Con più consumatori (paralleli), l’ordine di elaborazione non può essere garantito.
Il terzo paragrafo (incollato nella domanda) continua con una dichiarazione di non responsabilità, che parafrasò: “se si hanno più processori in coda, non c’è più la garanzia che i messaggi vengano elaborati in ordine”. Tutto quello che stanno dicendo qui è che RabbitMQ non può sfidare le leggi della matematica.

Considera una linea di clienti presso una banca. Questa particolare banca è orgogliosa di aiutare i clienti nell’ordine in cui sono entrati in banca. I clienti si allineano in coda e sono serviti dal terzo dei tre cassieri disponibili.

Stamattina, è successo che tutti e tre i cassieri sono diventati disponibili allo stesso tempo, e i successivi 3 clienti si sono avvicinati. All’improvviso, il primo dei tre scrutatori si ammalò violentemente e non riuscì a finire di servire il primo cliente della linea. Nel momento in cui ciò accadde, il cassiere 2 ebbe finito con il cliente 2 e il cassiere 3 aveva già iniziato a servire il cliente 3.

Ora, una delle due cose può accadere. (1) Il primo cliente in linea può tornare al capo della linea o (2) il primo cliente può anticipare il terzo cliente, facendo in modo che il cassiere smetta di funzionare sul terzo cliente e inizi a lavorare sul primo. Questo tipo di logica di prelazione non è supportato da RabbitMQ, né da altri broker di messaggi di cui sono a conoscenza. In entrambi i casi, il primo cliente in realtà non finisce per essere aiutato per primo – il secondo cliente lo fa, avendo la fortuna di avere un bravo, veloce teller. L’unico modo per garantire che i clienti siano aiutati è quello di avere un cassiere che aiuta i clienti uno alla volta, il che causerà importanti problemi di servizio alla cliencanvas per la banca.

Spero che questo aiuti a illustrare il problema che stai chiedendo. Non è ansible garantire che i messaggi vengano gestiti in ordine in ogni caso ansible, dato che si hanno più utenti. Non importa se hai più code, più clienti esclusivi, broker diversi, ecc. – non c’è modo di garantire a priori che i messaggi vengano risolti in ordine con più utenti. Ma RabbitMQ farà il massimo sforzo.

L’ordine dei messaggi è conservato in Kafka, ma solo all’interno delle partizioni anziché a livello globale. Se i tuoi dati hanno bisogno sia di ordini globali che di partizioni, questo rende le cose difficili. Tuttavia, se hai solo bisogno di assicurarti che tutti gli stessi eventi per lo stesso utente, ecc … finiscano nella stessa partizione in modo che siano ordinati correttamente, puoi farlo. Il produttore è responsabile della partizione su cui scrivono, quindi se si è in grado di suddividere i dati in modo logico potrebbe essere preferibile.

Penso che ci siano due cose in questa domanda che non sono simili, l’ordine di consumo e l’ordine di elaborazione.

Le Code dei messaggi possono, a un certo livello, darti la garanzia che i messaggi vengano consumati in ordine, tuttavia non possono darti alcuna garanzia sull’ordine di elaborazione.

La differenza principale qui è che ci sono alcuni aspetti dell’elaborazione dei messaggi che non possono essere determinati al momento del consumo, ad esempio:

  • Come accennato, un consumatore può fallire durante l’elaborazione, in questo caso l’ordine di consumo del messaggio era corretto, tuttavia, il consumatore non è riuscito a elaborarlo correttamente, il che lo farà tornare in coda e fino a ora l’ordine di consumo è ancora intatto ma non lo facciamo so come è ora l’ordine di elaborazione

  • Se per “elaborazione” intendiamo che il messaggio è ora scartato e terminato completamente, considera il caso in cui il tempo di elaborazione non è lineare, in altre parole l’elaborazione di un messaggio richiede più tempo di un’altra, quindi se il messaggio 3 richiede più tempo di elaborazione anticipato, i messaggi 4 e 5 potrebbero essere consumati e completare l’elaborazione prima del messaggio 3

Pertanto, anche se si è riusciti a riportare il messaggio nella parte anteriore della coda (che, a proposito, viola l’ordine di consumo), non è ancora ansible garantire che tutti i messaggi siano stati elaborati prima del successivo messaggio.

Se si desidera garantire l’ordine di elaborazione, quindi:

  1. Hai solo 1 istanza di consumo in ogni momento
  2. Oppure non utilizzare una coda di messaggistica e eseguire l’elaborazione in un metodo di blocco sincrono, che potrebbe sembrare sbagliato ma in molti casi e i requisiti aziendali sono completamente validi e talvolta anche critici