Questo articolo introduce innanzitutto quali problemi il middleware dei messaggi deve solitamente risolvere, quali difficoltà incontreranno nella risoluzione di questi problemi, se Apache RocketMQ può essere risolto come middleware di messaggi distribuiti ad alte prestazioni e ad alto throughput open source da Alibaba, e come questi problemi sono definiti nella specifica. Questo articolo introdurrà poi il design dell'architettura di RocketMQ, per offrire ai lettori una rapida comprensione di RocketMQ. 1. Quali problemi deve risolvere il middleware dei messaggi? Publish/Subscribe è la funzione più basilare del middleware dei messaggi ed è anche relativa alla comunicazione tradizionale RPC. Non entrerò nei dettagli qui. La priorità descritta nella specifica Priority dei Messaggi si riferisce a una coda di messaggi, ogni messaggio ha una priorità diversa, generalmente descritta da interi, il messaggio con alta priorità viene consegnato per primo; se il messaggio è completamente in una coda di memoria, può essere ordinato in base alla priorità prima della consegna, così che la priorità alta venga consegnata per prima. Poiché tutti i messaggi in RocketMQ sono persistenti, se ordinati secondo la priorità, il sovraccarico sarà molto elevato, quindi RocketMQ non supporta specificamente la priorità dei messaggi, ma può implementare funzioni simili in una soluzione alternativa, cioè configurare una coda con alta priorità e una coda con priorità normale, inviando priorità diverse a code diverse. Per le questioni prioritarie, possono essere riassunte in 2 categorie:
- Finché la priorità viene raggiunta, non è una priorità in senso stretto, e la priorità è solitamente divisa in livelli alti, medi, bassi o diversi altri livelli. Ogni priorità può essere rappresentata da un argomento diverso e, quando si invia un messaggio, specificare argomenti diversi per rappresentare la priorità, il che può risolvere la maggior parte dei problemi di priorità, ma compromettere l'accuratezza delle priorità aziendali.
- La priorità stretta si esprime come un intero, come 0 ~ 65535; questo tipo di problema di priorità generalmente non è adatto a essere risolto con argomenti diversi. Se vuoi che MQ risolva questo problema, avrà un impatto molto grande sulle prestazioni di MQ. Ecco un punto per assicurarsi che l'azienda abbia davvero bisogno di questa rigida prioritizzazione, e se le priorità vengono ridotte a poche, quanto impatto avrà sull'azienda?
L'Ordine dei Messaggi si riferisce a un tipo di messaggio che può essere consumato nell'ordine in cui viene inviato. Ad esempio, un ordine genera 3 messaggi, ovvero creazione dell'ordine, pagamento dell'ordine e completamento dell'ordine. Quando si consuma, è significativo consumare in questo ordine. Ma allo stesso tempo, gli ordini possono essere consumati in parallelo. RocketMQ può garantire rigorosamente che i messaggi siano ordinati. Filter MessaggiBroker Filtraggio messaggi Nel Broker, filtrare in base alle esigenze del consumatore ha il vantaggio di ridurre la trasmissione di messaggi non necessari al consumatore. Lo svantaggio è che aumenta il carico per il broker ed è relativamente complesso da implementare. 1. Taobao Notify supporta una varietà di metodi di filtraggio, incluso il filtraggio diretto per tipo di messaggio e il filtraggio flessibile, che può soddisfare quasi le esigenze di filtraggio più impegnative. 2. Taobao RocketMQ supporta il filtraggio tramite semplice Tag del Messaggio, oltre che tramite Intestazione e corpo del Messaggio. 3. Il filtraggio flessibile delle espressioni sintattice è supportato anche nella specifica CORBA Notification. Filtraggio dei messaggi lato consumatore Questo filtraggio può essere completamente personalizzato dall'applicazione, ma lo svantaggio è che molti messaggi inutili vengono inviati al consumatore. Esistono diversi metodi di persistenza comuni utilizzati dalla persistenza dei messaggi:
- Persisti su un database, come Mysql.
- Persiste su archiviazione KV, come levelDB, Berkeley DB e altri sistemi di archiviazione KV.
- Persistenza sotto forma di file record, come Kafka, RocketMQ
- Crea un'immagine persistente dei dati di memoria, come fagiolo magico, VisiNotify
- (1), (2) e (3) tutti e tre i metodi di persistenza hanno la capacità di estendere il buffer della coda di memoria, e (4) sono semplicemente un'immagine di memoria, che può comunque ripristinare i dati dalla memoria precedente dopo che il broker ha riattaccato e riavviato.
Le specifiche JMS e CORBA Notification non specificano esplicitamente come persistere, ma le prestazioni della parte di persistenza determinano direttamente le prestazioni dell'intero middleware del messaggio. RocketMQ sfrutta appieno la cache di memoria del file system Linux per migliorare le prestazioni. Ci sono diverse situazioni in cui la Affidabilità dei Messaggi influisce sull'affidabilità del messaggio:
- Il broker chiude normalmente
- Crollo del broker
- Crash del sistema operativo
- La macchina perde energia, ma l'alimentazione può essere ripristinata immediatamente.
- La macchina non si accende (potrebbe essere danneggiata su dispositivi chiave come CPU, scheda madre, memoria, ecc.)
- Danni al dispositivo disco.
(1), (2), (3) e (4) sono tutte situazioni in cui le risorse hardware possono essere recuperate immediatamente, e RocketMQ può garantire che i messaggi non vengano persi o che una piccola quantità di dati venga persa (a seconda che il metodo di flashing sia sincrono o asincrono). (5) (6) Si tratta di un unico punto di guasto e non può essere recuperato; una volta che si verifica, tutti i messaggi su quel singolo punto vengono persi. In entrambi i casi, RocketMQ garantisce che il 99% dei messaggi non venga perso tramite replica asincrona, ma ci sono comunque pochissimi messaggi che potrebbero andare persi. La tecnologia di scrittura doppia sincrona può evitare completamente i singoli punti, che inevitabilmente influenzeranno le prestazioni, rendendola adatta a situazioni con requisiti di affidabilità dei messaggi estremamente elevati, come le applicazioni legate al denaro. RocketMQ supporta la scrittura doppia sincrona a partire dalla versione 3.0. La messaggistica a bassa latenza può raggiungere il consumatore immediatamente dopo che il messaggio è arrivato al broker senza accumulare messaggi. RocketMQ utilizza un metodo di pulling lungo per garantire che il messaggio sia molto in tempo reale e che il messaggio in tempo reale non sia inferiore a quello del push. Almeno una volta significa che ogni messaggio deve essere consegnato una sola volta. RocketMQ Consumer prima trasmette il messaggio nell'area locale, poi restituisce l'ack al server dopo il consumo. Esattamente solo una volta- La fase di invio dei messaggi non consente l'invio di messaggi duplicati.
- Nella fase Consume Message, i messaggi duplicati non possono essere consumati.
Solo quando le due condizioni sopra sono soddisfatte il messaggio può essere considerato "Esattamente Solo una volta", e per raggiungere i due punti sopra, inevitabilmente verrà generato un enorme overhead nell'ambiente del sistema distribuito. Pertanto, per perseguire alte prestazioni, RocketMQ non garantisce questa funzionalità e richiede la deduplicazione nell'azienda, il che significa che i messaggi dei consumatori devono essere idempotenti. Sebbene RocketMQ non possa garantire rigorosamente la non duplicazione, in circostanze normali raramente si ripetono invii e consumi, solo anomalie di rete, avvio e arresto del consumatore e altre situazioni anomale come la duplicazione dei messaggi. La ragione essenziale di questo problema è che esiste incertezza nelle chiamate di rete, cioè il terzo stato di non successo né di fallimento, quindi sorge il problema della ripetizione dei messaggi. Cosa dovrei fare se il Broker's Buffer è pieno? Il buffer del broker di solito si riferisce alla dimensione del buffer di memoria di una coda nel broker, che di solito è limitata in dimensioni; cosa succede se il buffer è pieno? Ecco come viene gestito nella specifica di notifica CORBA:
- RejectNewEvents rifiuta il nuovo messaggio e restituisce il codice di errore RejectNewEvents al Producer.
- Scartare i messaggi esistenti secondo una politica specifica
- AnyOrder - Qualsiasi evento può essere scartato in overflow. Questa è l'impostazione predefinita per questa proprietà.
- FifoOrder - Il primo evento ricevuto sarà il primo scartato.
- LifoOrder - L'ultimo evento ricevuto sarà il primo scartato.
- Ordine di priorità - Gli eventi devono essere scartati in ordine di priorità, in modo che gli eventi di priorità inferiore vengano scartati prima di quelli di priorità superiore.
- DeadlineOrder - Gli eventi dovrebbero essere scartati prima nell'ordine della scadenza più breve.
RocketMQ non ha il concetto di memory buffer, e le code di RocketMQ sono dischi persistenti, e i dati vengono cancellati regolarmente. Per risolvere questo problema, RocketMQ presenta una differenza molto significativa rispetto ad altri MQ: il buffer di memoria di RocketMQ è astratto in una coda di lunghezza infinita, indipendentemente da quanti dati arrivino, può essere installato, questa infinità è basata sul presupposto, il broker cancella regolarmente i dati scaduti, ad esempio, il broker salva solo 3 giorni di messaggi, poi, anche se la lunghezza di questo buffer è infinita, i dati di 3 giorni prima vengono cancellati dalla fine della coda. Il consumo retroattivo si riferisce al messaggio che il consumatore ha consumato con successo e che il messaggio deve essere riconsumato a causa della domanda aziendale. Ad esempio, a causa del guasto del sistema consumer, i dati di un'ora fa devono essere riconsumati dopo il recupero, quindi il broker dovrebbe fornire un meccanismo per invertire il progresso del consumo in base alla dimensione temporale. RocketMQ supporta il consumo retroattivo basato sul tempo, con una dimensione temporale precisa ai millisecondi, che può essere retrocedibile in avanti o indietro. La funzione principale del middleware di messaggi stacking è il decoupling asincrono, e un'altra funzione importante è bloccare il picco di flood dati del front-end e garantire la stabilità del sistema back-end, che richiede che il middleware dei messaggi abbia una certa capacità di stacking di messaggi, e il message heap integra le seguenti due situazioni:
- I messaggi vengono accumulati in buffer di memoria e, una volta superati il buffer di memoria, i messaggi possono essere eliminati secondo una certa policy di drop, come descritto nella specifica di notifica CORBA. È adatto a servizi che tollerano lo scartamento dei messaggi; in questo caso, la capacità di accumulo dei messaggi dipende principalmente dalla dimensione del buffer di memoria, e il degrado delle prestazioni non sarà troppo grande dopo l'impilamento del messaggio, poiché la quantità di dati in memoria ha un impatto limitato sulla capacità di accesso fornita al mondo esterno.
- I messaggi sono accumulati in sistemi di archiviazione persistenti come DB, KV storage, file record form. Quando i messaggi non possono essere trovati nella cache di memoria, è inevitabile accedere al disco, che genera una grande quantità di IO di lettura, e la velocità di output di lettura determina direttamente la capacità di accesso dei messaggi dopo che sono stati accumulati.
Ci sono quattro punti principali per valutare la capacità di accumulo dei messaggi:
- Quanti messaggi si possono accumulare, quanti byte? Cioè, la capacità di accumulo del messaggio.
- Dopo che un messaggio è stato accumulato, la velocità di trasmissione del messaggio è influenzata dall'impilamento?
- Il consumo normale dei consumatori sarà influenzato dopo che i messaggi si accumulano?
- Dopo che i messaggi sono stati accumulati, qual è la velocità di trasmissione quando si accedono ai messaggi accumulati sul disco?
Transazioni distribuite Diverse specifiche note di transazioni distribuite, come XA, JTA, ecc. Tra questi, la specifica XA è ampiamente supportata dai principali fornitori di database, come Oracle, Mysql, ecc. Tra questi, il leader dell'implementazione TM di XA, come Oracle Tuxedo, è ampiamente utilizzato in finanza, telecomunicazioni e altri settori. Le transazioni distribuite comportano problemi di commit a due fasi e, in termini di archiviazione dati, lo storage KV deve essere supportato, perché la seconda fase del rollback del commit deve modificare lo stato del messaggio, il che deve comportare l'azione di trovare il messaggio secondo la chiave. RocketMQ bypassa il problema di trovare il messaggio secondo la chiave nel secondo stadio, usando il primo stadio per inviare il messaggio preparato, ottenendo l'offset del messaggio, e il secondo stadio per accedere al messaggio tramite l'offset e modificare lo stato; l'offset è l'indirizzo dei dati. Il metodo di implementazione delle transazioni di RocketMQ non viene effettuato tramite lo storage KV, ma tramite il metodo offset, che presenta un difetto significativo, ovvero che cambiare i dati tramite offset causerà troppe pagine sporche nel sistema, richiedendo particolare attenzione. Messaggi programmati I messaggi programmati significano che i messaggi non possono essere consumati dai consumatori immediatamente dopo essere stati inviati al broker, e possono essere consumati solo in un momento specifico o dopo aver atteso un orario specifico. Se vuoi supportare un'accuratezza temporale arbitraria, a livello di broker devi fare l'ordinamento dei messaggi, e se c'è persistenza, allora l'ordinamento dei messaggi comporterà inevitabilmente un enorme sovraccarico di prestazioni. RocketMQ supporta i messaggi di temporizzazione, ma non supporta un'accuratezza temporale arbitraria e supporta livelli specifici, come il cronometraggio di 5, 10, 1m, ecc. Ritenta il messaggio Dopo che il consumatore non riesce a consumare il messaggio, prevedi un meccanismo di ritentativo per far consumare nuovamente il messaggio. I fallimenti dei messaggi di consumo dei consumatori possono solitamente essere considerati nelle seguenti situazioni:
- A causa del motivo stesso del messaggio, come il fallimento della deerializzazione, i dati del messaggio non possono essere elaborati (come la ricarica della bolletta telefonica, il numero di cellulare del messaggio corrente è disconnesso, non può essere ricaricato), ecc. Questo errore di solito richiede di saltare questo messaggio e di consumare altri messaggi, e questo messaggio fallito è fallito al 99% anche se il consumo viene riprovato immediatamente, quindi è meglio fornire un meccanismo di ritentazione temporizzata, cioè ritentare dopo 10 secondi.
- Poiché i servizi applicativi a valle dipendenti non sono disponibili, come la connessione al DB non disponibile, la rete di sistema esterna non raggiungibile, ecc. Quando si verifica questo errore, anche se il messaggio fallito attuale viene saltato, verranno consumati anche altri messaggi. In questo caso, si consiglia di applicare un sleep 30s e consumare il messaggio successivo, il che può ridurre la pressione sul broker per riprovare il messaggio.
Panoramica di RocketMQ Scopriamo se RocketMQ risolve i problemi affrontati dal middleware dei messaggi menzionato sopra.
Cos'è RocketMQ?
La figura sopra è un modello tipico di middleware di messaggi che inviano e ricevono messaggi; anche RocketMQ è progettato in questo modo; in breve, RocketMQ possiede le seguenti caratteristiche:
- Si tratta di un middleware di messaggi a coda con alte prestazioni, alta affidabilità, alta capacità in tempo reale e distribuite.
- Produttore, Consumatore e Coda possono essere distribuiti.
- Il produttore invia messaggi ad alcune code a turno, la raccolta della coda si chiama Topic, Consumer If broadcast consumption, un'istanza consumer consuma tutte le code corrispondenti a questo argomento, e in caso di consumo cluster, più istanze consumer consumano la collezione di code corrispondente a questo argomento in modo uniforme.
- Un ordine dei messaggi rigoroso può essere garantito
- Fornisce modalità di pull dei messaggi ricche
- Capacità efficienti di scalabilità orizzontale degli abbonati
- Meccanismo di abbonamento ai messaggi in tempo reale
- Capacità di accumulo di centinaia di milioni di messaggi
- Minore dipendenza
Struttura fisica di dispiegamento RocketMQ
Come mostrato nella figura sopra, la struttura di dispiegamento di RocketMQ presenta le seguenti caratteristiche:
- Il Name Server è un nodo praticamente senza stato che può essere distribuito in cluster senza alcuna sincronizzazione delle informazioni tra i nodi.
- L'impiego di Broker è relativamente complesso, Broker è diviso in Master e Slave, un Master può corrispondere a più Slave, ma uno Slave può corrispondere solo a un Master, la corrispondenza tra Master e Slave è definita specificando lo stesso BrokerName, un BrokerId diverso, BrokerId è 0 per Master, e non-0 significa Slave. I master possono anche essere utilizzati in più di uno. Ogni broker stabilisce una lunga connessione con tutti i nodi del cluster dei Name Server e registra le informazioni sugli argomenti a tutti i Name Server a intervalli regolari.
- Il produttore stabilisce una lunga connessione con uno dei nodi del cluster Name Server (selezionato casualmente), recupera periodicamente le informazioni di routing degli argomenti dal Name Server, stabilisce una lunga connessione con il master che fornisce il servizio di argomento e invia battiti cardiaci al master a intervalli regolari. Producer è completamente senza stato e può essere distribuito in cluster.
- Il consumatore stabilisce una connessione lunga con uno dei nodi del cluster del server di nomi (selezionato casualmente), recupera regolarmente le informazioni di routing degli argomenti dal server di nomi e stabilisce una connessione lunga con il Master e lo Slave che forniscono il servizio di argomento, inviando battiti cardiaci al Master e allo Slave a intervalli regolari. I consumatori possono abbonarsi ai messaggi sia del Master che dello Slave, e le regole di abbonamento sono determinate dalla configurazione del Broker.
Struttura di distribuzione logica RocketMQ
Come mostrato nella figura sopra, la struttura logica di distribuzione di RocketMQ ha due caratteristiche: Produttore e Consumatore.
Utilizzato per rappresentare un'applicazione di messaggistica, un Gruppo Produttore contiene più istanze Producer, che possono essere più macchine, molteplici processi di una macchina o più oggetti Producer di un processo. Un Gruppo Produttori può inviare più messaggi Topic, e il Gruppo Produttori funziona come segue:
- Identifica un tipo di produttore
- Puoi verificare che ci siano più istanze Producer in questa applicazione di messaggistica tramite lo strumento O&M
- Quando si invia un messaggio di transazione distribuita, se il produttore cade improvvisamente, il broker richiamerà attivamente qualsiasi macchina del gruppo di produttori per confermare lo stato della transazione.
Utilizzato per rappresentare un'applicazione di messaggistica per consumatori, un gruppo di consumatori contiene molteplici istanze di consumo, che possono essere più macchine, più processi o più oggetti consumatori di un processo. Più consumatori in un Gruppo di Consumatori consumano i messaggi in modo uniformemente distribuito e, se impostato su trasmissione, ogni istanza di questo Gruppo di Consumatori consuma l'intera quantità di dati.
Struttura di archiviazione dati RocketMQ
Come mostrato nella figura sopra, RocketMQ adotta un metodo di archiviazione che separa i dati dagli indici. Ridurre efficacemente la perdita di risorse di file, risorse IO e memorie. Anche con dati massicci come Alibaba, scenari ad alta concorrenza possono ridurre efficacemente la latenza end-to-end e avere forti capacità di scala orizzontale.
|