
Η ανοχή σφαλμάτων και η υψηλή διαθεσιμότητα είναι μεγάλα θέματα, επομένως θα αφιερώσουμε ξεχωριστά άρθρα στο RabbitMQ και τον Kafka. Αυτό το άρθρο είναι για το RabbitMQ και το επόμενο είναι για τον Κάφκα, σε σύγκριση με το RabbitMQ. Αυτό είναι ένα μεγάλο άρθρο, οπότε βολευτείτε.
Ας δούμε τις στρατηγικές ανοχής σφαλμάτων, συνέπειας και υψηλής διαθεσιμότητας (HA) και τις ανταλλαγές που εμπλέκονται σε κάθε στρατηγική. Το RabbitMQ μπορεί να τρέξει σε ένα σύμπλεγμα κόμβων - και στη συνέχεια ταξινομείται ως κατανεμημένο σύστημα. Όταν μιλάμε για κατανεμημένα συστήματα, μιλάμε συχνά για συνέπεια και διαθεσιμότητα.
Αυτές οι έννοιες περιγράφουν πώς συμπεριφέρεται το σύστημα όταν συμβαίνει μια αστοχία. Αποτυχία σύνδεσης δικτύου, αποτυχία διακομιστή, αποτυχία σκληρού δίσκου, διακομιστής προσωρινά μη διαθέσιμος λόγω συλλογής σκουπιδιών, απώλειας πακέτων ή αργής σύνδεσης δικτύου. Όλα αυτά μπορεί να οδηγήσουν σε απώλεια δεδομένων ή συγκρούσεις. Αποδεικνύεται ότι είναι σχεδόν αδύνατο να δημιουργηθεί ένα σύστημα που να είναι ταυτόχρονα απόλυτα συνεπές (χωρίς απώλεια δεδομένων, χωρίς αποκλίσεις δεδομένων) και προσβάσιμο (θα δέχεται λειτουργίες ανάγνωσης και εγγραφής) για όλες τις καταστάσεις αποτυχίας.
Θα δούμε ότι η συνέπεια και η διαθεσιμότητα βρίσκονται σε διαφορετικά άκρα του φάσματος και θα πρέπει να επιλέξετε ποιο θα βελτιστοποιήσετε. Τα καλά νέα είναι ότι με το RabbitMQ αυτή η επιλογή είναι δυνατή. Έχετε αυτούς τους μικροσκοπικούς μοχλούς για να αλλάξετε την ισορροπία προς περισσότερη συνοχή ή περισσότερη προσβασιμότητα.
Θα δώσουμε ιδιαίτερη προσοχή στο ποιες διαμορφώσεις οδηγούν σε απώλεια δεδομένων λόγω δεσμευμένων εγγραφών. Υπάρχει μια αλυσίδα ευθύνης μεταξύ των εκδοτών, των μεσιτών και των καταναλωτών. Μόλις περάσει ένα μήνυμα στον μεσίτη, είναι δουλειά του να μην χάσει το μήνυμα. Όταν ένας μεσίτης επιβεβαιώνει τη λήψη ενός μηνύματος σε έναν εκδότη, δεν περιμένουμε να χαθεί. Αλλά θα δούμε ότι αυτό μπορεί πράγματι να συμβεί ανάλογα με τη διαμόρφωση του μεσίτη και του εκδότη σας.
Single Node Stability Primitives
Μόνιμες ουρές/δρομολόγηση
Το RabbitMQ έχει δύο τύπους ουρών: ανθεκτικό και μη ανθεκτικό. Όλες οι ουρές αποθηκεύονται στη βάση δεδομένων Mnesia. Οι ανθεκτικές ουρές ανακοινώνονται εκ νέου όταν ξεκινά ένας κόμβος και έτσι επιβιώνουν από επανεκκίνηση, συντριβή συστήματος ή αποτυχία διακομιστή (εφόσον τα δεδομένα επιμένουν). Αυτό σημαίνει ότι όσο δηλώνετε την ανταλλαγή και την ουρά ως ανθεκτικές, η υποδομή ουράς/δρομολόγησης θα επανέλθει στο διαδίκτυο.
Οι ασταθείς ουρές και η δρομολόγηση αφαιρούνται κατά την επανεκκίνηση του κόμβου.
Επίμονα μηνύματα
Ακριβώς επειδή μια ουρά είναι μεγάλης διάρκειας δεν σημαίνει ότι όλα τα μηνύματά της θα επιβιώσουν από την επανεκκίνηση του κόμβου. Μόνο μηνύματα που έχουν οριστεί από τον εκδότη ως βιώσιμη (επίμονος). Τα μόνιμα μηνύματα δημιουργούν πρόσθετο φορτίο στον μεσίτη, αλλά εάν η απώλεια μηνύματος είναι απαράδεκτη, τότε δεν υπάρχει άλλος τρόπος.

Ρύζι. 1. Πίνακας σταθερότητας
Ομαδοποίηση με κατοπτρισμό ουρών
Για να επιβιώσουμε από την απώλεια ενός μεσίτη, χρειαζόμαστε πλεονασμό. Μπορούμε να συνδυάσουμε πολλούς κόμβους RabbitMQ σε ένα σύμπλεγμα και στη συνέχεια να προσθέσουμε επιπλέον πλεονασμό αναπαράγοντας ουρές σε πολλούς κόμβους. Με αυτόν τον τρόπο, εάν ένας κόμβος πέσει, δεν χάνουμε δεδομένα και παραμένουμε διαθέσιμοι.
Κατοπτρισμός ουράς:
- μία κύρια ουρά (κύρια) που λαμβάνει όλες τις εντολές εγγραφής και ανάγνωσης
- έναν ή περισσότερους καθρέφτες που λαμβάνουν όλα τα μηνύματα και τα μεταδεδομένα από την κύρια ουρά. Αυτοί οι καθρέφτες δεν υπάρχουν για κλιμάκωση, αλλά καθαρά για πλεονασμό.

Ρύζι. 2. Καθρεφτισμός ουράς
Το mirroring ορίζεται από την αντίστοιχη πολιτική. Σε αυτό μπορείτε να επιλέξετε τον παράγοντα αναπαραγωγής και ακόμη και τους κόμβους στους οποίους θα πρέπει να τοποθετηθεί η ουρά. Παραδείγματα:
ha-mode: allha-mode: exactly, ha-params: 2(ένας κύριος και ένας καθρέφτης)ha-mode: nodes, ha-params: rabbit@node1, rabbit@node2
Επιβεβαίωση στον εκδότη
Απαιτούνται επιβεβαιώσεις εκδότη για την επίτευξη συνεπούς εγγραφής. Χωρίς αυτά, υπάρχει κίνδυνος απώλειας μηνυμάτων. Μια επιβεβαίωση αποστέλλεται στον εκδότη μετά την εγγραφή του μηνύματος στο δίσκο. Το RabbitMQ γράφει μηνύματα στο δίσκο όχι κατά την παραλαβή, αλλά σε περιοδική βάση, στην περιοχή μερικών εκατοντάδων χιλιοστών του δευτερολέπτου. Όταν αντικατοπτρίζεται μια ουρά, αποστέλλεται μια επιβεβαίωση μόνο αφού όλοι οι καθρέφτες έχουν επίσης γράψει το αντίγραφό τους του μηνύματος στο δίσκο. Αυτό σημαίνει ότι η χρήση επιβεβαιώσεων προσθέτει καθυστέρηση, αλλά εάν η ασφάλεια των δεδομένων είναι σημαντική, τότε είναι απαραίτητες.
Ουρά ανεκτική σε σφάλματα
Όταν ένας μεσίτης τερματίζει ή κολλάει, όλοι οι κύριοι σε αυτόν τον κόμβο πέφτουν μαζί του. Στη συνέχεια, το σύμπλεγμα επιλέγει τον παλαιότερο καθρέφτη κάθε πλοιάρχου και τον προωθεί ως νέο κύριο.

Ρύζι. 3. Πολλαπλές αντικατοπτρισμένες ουρές και οι πολιτικές τους
Το Broker 3 είναι εκτός λειτουργίας. Λάβετε υπόψη ότι ο καθρέφτης της ουράς C στο Broker 2 προωθείται σε κύριο. Σημειώστε επίσης ότι έχει δημιουργηθεί ένας νέος καθρέφτης για την ουρά C στο Broker 1. Το RabbitMQ προσπαθεί πάντα να διατηρεί τον παράγοντα αναπαραγωγής που καθορίζεται στις πολιτικές σας.

Ρύζι. 4. Το Broker 3 πέφτει, προκαλώντας αποτυχία της ουράς C.
Το επόμενο Broker 1 πέφτει! Έχουμε μόνο έναν μεσίτη. Ο καθρέφτης της ουράς Β προωθείται σε κύριο.

Σχήμα. 5
Επιστρέψαμε το Broker 1. Ανεξάρτητα από το πόσο καλά επιβίωσαν τα δεδομένα από την απώλεια και την ανάκτηση του μεσίτη, όλα τα αντικατοπτρισμένα μηνύματα ουράς απορρίπτονται κατά την επανεκκίνηση. Αυτό είναι σημαντικό να σημειωθεί γιατί θα υπάρξουν συνέπειες. Θα εξετάσουμε αυτές τις επιπτώσεις σύντομα. Έτσι, ο Broker 1 είναι πλέον μέλος του συμπλέγματος και το σύμπλεγμα προσπαθεί να συμμορφωθεί με τις πολιτικές και ως εκ τούτου δημιουργεί καθρέφτες στο Broker 1.
Σε αυτήν την περίπτωση, η απώλεια του Broker 1 ήταν ολική, όπως και τα δεδομένα, οπότε η ουρά Β που δεν είχε αντικατοπτριστεί χάθηκε εντελώς.

Ρύζι. 6. Ο Broker 1 επιστρέφει στη δράση
Το Broker 3 επιστρέφει στο διαδίκτυο, επομένως οι ουρές Α και Β δημιουργούν τους καθρέφτες τους για να ικανοποιήσουν τις πολιτικές τους HA. Τώρα όμως όλες οι κύριες ουρές βρίσκονται σε έναν κόμβο! Αυτό δεν είναι ιδανικό, μια ομοιόμορφη κατανομή μεταξύ των κόμβων είναι καλύτερη. Δυστυχώς, δεν υπάρχουν ειδικές επιλογές για την εξισορρόπηση των πλοιάρχων εδώ. Θα επανέλθουμε σε αυτό το πρόβλημα αργότερα, καθώς πρέπει πρώτα να εξετάσουμε το συγχρονισμό της ουράς.

Ρύζι. 7. Ο μεσίτης 3 επιστρέφει στην υπηρεσία. Όλες οι κύριες ουρές σε έναν κόμβο!
Έτσι, θα πρέπει τώρα να έχετε μια ιδέα για το πώς οι καθρέφτες παρέχουν πλεονασμό και ανοχή σφαλμάτων. Αυτό διασφαλίζει τη διαθεσιμότητα σε περίπτωση αποτυχίας ενός μεμονωμένου κόμβου και προστατεύει από απώλεια δεδομένων. Αλλά δεν έχουμε τελειώσει ακόμα, γιατί στην πραγματικότητα, όλα είναι πολύ πιο περίπλοκα.
Συγχρονισμός
Όταν δημιουργείτε έναν νέο καθρέφτη, όλα τα νέα μηνύματα θα αναπαράγονται πάντα σε αυτόν τον καθρέφτη και σε οποιοδήποτε άλλο. Όσον αφορά τα υπάρχοντα δεδομένα στην κύρια ουρά, μπορούμε να τα αντιγράψουμε σε ένα νέο καθρέφτη, το οποίο γίνεται πλήρες αντίγραφο του κύριου. Μπορούμε επίσης να επιλέξουμε να μην αναπαράγουμε υπάρχοντα μηνύματα και να αφήσουμε την κύρια ουρά και το νέο καθρέφτη να συγκλίνουν εγκαίρως καθώς τα νέα μηνύματα φτάνουν στην ουρά και τα υπάρχοντα μηνύματα φεύγουν από το κεφάλι της κύριας ουράς.
Αυτός ο συγχρονισμός εκτελείται αυτόματα ή μη αυτόματα και ελέγχεται από μια πολιτική ουράς. Ας δούμε ένα παράδειγμα.
Έχουμε δύο καθρέφτες ουρές. Η ουρά Α συγχρονίζεται αυτόματα, ενώ η ουρά Β συγχρονίζεται χειροκίνητα. Υπάρχουν δέκα μηνύματα και στις δύο ουρές.

Ρύζι. 8. Δύο ουρές με διαφορετικούς τρόπους συγχρονισμού
Τώρα χάνουμε το Broker 3.

Ρύζι. 9. Ο μεσίτης 3 έπεσε
Το Broker 3 επιστρέφει στη δράση. Το σύμπλεγμα δημιουργεί έναν καθρέφτη για κάθε ουρά στον νέο κόμβο και συγχρονίζει αυτόματα τη νέα ουρά Α με την κύρια. Ωστόσο, ο καθρέφτης του νέου Queue B παραμένει κενός. Έτσι, έχουμε πλήρη πλεονασμό της ουράς Α και μόνο έναν καθρέφτη για υπάρχοντα μηνύματα της ουράς Β.

Ρύζι. 10. Ο νέος καθρέφτης της ουράς Α λαμβάνει όλα τα υπάρχοντα μηνύματα, αλλά ο νέος καθρέφτης της ουράς Β όχι.
Δέκα ακόμη μηνύματα φτάνουν και στις δύο ουρές. Στη συνέχεια, το Broker 2 διακόπτεται και η ουρά Α επιστρέφει στον παλαιότερο καθρέφτη, ο οποίος βρίσκεται στο Broker 1. Δεν υπάρχει απώλεια δεδομένων όταν συμβεί το σφάλμα. Η ουρά Β έχει είκοσι μηνύματα στο κύριο και μόνο δέκα στον καθρέφτη, επειδή αυτή η ουρά δεν αναπαρήγαγε ποτέ τα αρχικά δέκα μηνύματα.

Ρύζι. 11. Η ουρά Α επιστρέφει στο Broker 1 χωρίς να χαθούν μηνύματα
Δέκα ακόμη μηνύματα φτάνουν και στις δύο ουρές. Τώρα το Broker 1 κολλάει. Η ουρά Α μεταβαίνει στον καθρέφτη χωρίς προβλήματα και χωρίς απώλεια μηνυμάτων. Ωστόσο, η ουρά Β αντιμετωπίζει προβλήματα. Σε αυτό το στάδιο μπορούμε να βελτιστοποιήσουμε είτε τη διαθεσιμότητα είτε τη συνέπεια.
Αν θέλουμε να βελτιστοποιήσουμε την προσβασιμότητα, τότε η πολιτική χα-προώθηση-σε-αποτυχία πρέπει να εγκατασταθεί σε πάντοτε. Αυτή είναι η προεπιλεγμένη τιμή, επομένως απλά δεν μπορείτε να καθορίσετε καθόλου την πολιτική. Σε αυτήν την περίπτωση, ουσιαστικά επιτρέπουμε αστοχίες σε μη συγχρονισμένους καθρέφτες. Αυτό θα έχει ως αποτέλεσμα την απώλεια μηνυμάτων, αλλά η ουρά θα παραμείνει διαθέσιμη για ανάγνωση και εγγραφή.

Ρύζι. 12. Η ουρά Α επιστρέφει στο Broker 3 χωρίς να χαθούν μηνύματα. Η ουρά Β επιστρέφει στο Broker 3 με την απώλεια δέκα μηνυμάτων
Μπορούμε επίσης να εγκαταστήσουμε ha-promote-on-failure σε νόημα when-synced. Σε αυτήν την περίπτωση, αντί να επιστρέψει στον καθρέφτη, η ουρά θα περιμένει μέχρι το Broker 1 με τα δεδομένα του να επιστρέψει σε λειτουργία λειτουργίας. Μετά την επιστροφή του, η κύρια ουρά βρίσκεται ξανά στο Broker 1 χωρίς καμία απώλεια δεδομένων. Η διαθεσιμότητα θυσιάζεται για την ασφάλεια των δεδομένων. Αλλά αυτή είναι μια επικίνδυνη λειτουργία που μπορεί να οδηγήσει ακόμη και σε πλήρη απώλεια δεδομένων, την οποία θα εξετάσουμε σύντομα.

Ρύζι. 13. Η ουρά Β παραμένει μη διαθέσιμη μετά την απώλεια του Broker 1
Μπορείτε να ρωτήσετε, "Ίσως είναι καλύτερο να μην χρησιμοποιείτε ποτέ τον αυτόματο συγχρονισμό;" Η απάντηση είναι ότι ο συγχρονισμός είναι μια λειτουργία αποκλεισμού. Κατά τη διάρκεια του συγχρονισμού, η κύρια ουρά δεν μπορεί να εκτελέσει λειτουργίες ανάγνωσης ή εγγραφής!
Ας δούμε ένα παράδειγμα. Έχουμε πολύ μεγάλες ουρές τώρα. Πώς μπορούν να μεγαλώσουν σε τέτοιο μέγεθος; Για διάφορους λόγους:
- Οι ουρές δεν χρησιμοποιούνται ενεργά
- Πρόκειται για ουρές υψηλής ταχύτητας και αυτή τη στιγμή οι καταναλωτές εργάζονται αργά.
- Αυτές είναι ουρές υψηλής ταχύτητας, υπήρξε πρόβλημα και οι καταναλωτές προλαβαίνουν

Ρύζι. 14. Δύο μεγάλες ουρές με διαφορετικούς τρόπους συγχρονισμού
Τώρα το Broker 3 πέφτει.

Ρύζι. 15. Το Broker 3 κολλάει, αφήνοντας ένα master και mirror σε κάθε ουρά
Το Broker 3 επιστρέφει στο διαδίκτυο και δημιουργούνται νέοι καθρέφτες. Η κύρια ουρά Α αρχίζει να αναπαράγει υπάρχοντα μηνύματα σε νέο καθρέφτη και κατά τη διάρκεια αυτής της περιόδου η ουρά δεν είναι διαθέσιμη. Χρειάζονται δύο ώρες για την αναπαραγωγή των δεδομένων, με αποτέλεσμα δύο ώρες διακοπής λειτουργίας για αυτήν την ουρά!
Ωστόσο, η ουρά Β παραμένει διαθέσιμη καθ' όλη τη διάρκεια της περιόδου. Θυσίασε κάποιο πλεονασμό για την προσβασιμότητα.

Ρύζι. 16. Η ουρά παραμένει μη διαθέσιμη κατά τον συγχρονισμό
Μετά από δύο ώρες, η ουρά Α γίνεται επίσης διαθέσιμη και μπορεί να αρχίσει ξανά να δέχεται λειτουργίες ανάγνωσης και εγγραφής.
Ενημερώσεις
Αυτή η συμπεριφορά αποκλεισμού κατά τον συγχρονισμό καθιστά δύσκολη την ενημέρωση συμπλεγμάτων με πολύ μεγάλες ουρές. Σε κάποιο σημείο, ο κύριος κόμβος πρέπει να επανεκκινηθεί, πράγμα που σημαίνει είτε αλλαγή σε καθρέφτη είτε απενεργοποίηση της ουράς ενώ ο διακομιστής ενημερώνεται. Εάν επιλέξουμε τη μετεγκατάσταση, θα χάσουμε μηνύματα εάν οι καθρέφτες δεν είναι συγχρονισμένοι. Από προεπιλογή, όταν αποσυνδέεται ένας μεσίτης, δεν εκτελείται η εναλλαγή σε μη συγχρονισμένο καθρέφτη. Αυτό σημαίνει ότι μόλις επιστρέψει ο μεσίτης, δεν χάνουμε κανένα μήνυμα, η μόνη ζημιά είναι μόνο ο χρόνος διακοπής της ουράς. Οι κανόνες συμπεριφοράς κατά την απενεργοποίηση ενός μεσίτη καθορίζονται από την πολιτική ha-promote-on-shutdown. Μπορείτε να ορίσετε μία από τις δύο τιμές:
always= η μετάβαση σε μη συγχρονισμένους καθρέφτες είναι ενεργοποιημένηwhen-synced= μετάβαση μόνο σε συγχρονισμένο καθρέφτη, διαφορετικά η ουρά δεν θα είναι διαθέσιμη για ανάγνωση και εγγραφή. Η ουρά θα επανέλθει στη σειρά μόλις επιστρέψει ο μεσίτης.
Είτε έτσι είτε αλλιώς, με μεγάλες ουρές πρέπει να επιλέξετε μεταξύ απώλειας δεδομένων και μη διαθεσιμότητας.
Όταν η διαθεσιμότητα βελτιώνει την ασφάλεια δεδομένων
Υπάρχει μια ακόμη επιπλοκή που πρέπει να εξετάσετε πριν λάβετε μια απόφαση. Ενώ ο αυτόματος συγχρονισμός είναι καλύτερος για πλεονασμό, πώς επηρεάζει την ασφάλεια των δεδομένων; Σίγουρα, χάρη στον καλύτερο πλεονασμό, το RabbitMQ είναι λιγότερο πιθανό να χάσει τα υπάρχοντα μηνύματα, αλλά τι γίνεται με τα νέα μηνύματα από εκδότες;
Εδώ πρέπει να λάβετε υπόψη τα ακόλουθα:
- Μπορεί ο εκδότης απλώς να επιστρέψει ένα σφάλμα και η υπηρεσία ή ο χρήστης ανοδικής ροής μπορεί να προσπαθήσει ξανά αργότερα;
- Μπορεί ο εκδότης να αποθηκεύσει το μήνυμα τοπικά ή σε μια βάση δεδομένων για να προσπαθήσει ξανά αργότερα;
Εάν ένας εκδότης μπορεί να απορρίψει μόνο ένα μήνυμα, τότε στην πραγματικότητα, η βελτίωση της προσβασιμότητας βελτιώνει επίσης την ασφάλεια των δεδομένων.
Επομένως, είναι απαραίτητο να αναζητήσετε μια ισορροπία και η λύση εξαρτάται από τη συγκεκριμένη κατάσταση.
Προβλήματα με το ha-promote-on-failure=when-synced
Ιδέα χα-προώθηση-σε-αποτυχία= όταν-συγχρονίζεται είναι ότι αποτρέπουμε τη μετάβαση σε μη συγχρονισμένο καθρέφτη και έτσι αποφεύγουμε την απώλεια δεδομένων. Η ουρά παραμένει μη διαθέσιμη για ανάγνωση ή γραφή. Αντίθετα, προσπαθούμε να επαναφέρουμε τον μεσίτη που έχει καταρρεύσει με άθικτα δεδομένα, ώστε να μπορεί να συνεχίσει να λειτουργεί ως κύριος χωρίς απώλεια δεδομένων.
Αλλά (και αυτό είναι μεγάλο αλλά) εάν ο μεσίτης έχει χάσει τα δεδομένα του, τότε έχουμε ένα μεγάλο πρόβλημα: η ουρά έχει χαθεί! Όλα τα δεδομένα χάνονται! Ακόμα κι αν έχετε καθρέφτες που φτάνουν ως επί το πλείστον με την κύρια ουρά, αυτοί οι καθρέφτες επίσης απορρίπτονται.
Για να προσθέσουμε ξανά έναν κόμβο με το ίδιο όνομα, λέμε στο σύμπλεγμα να ξεχάσει τον χαμένο κόμβο (χρησιμοποιώντας την εντολή rabbitmqctl forget_cluster_node) και ξεκινήστε έναν νέο μεσίτη με το ίδιο όνομα κεντρικού υπολογιστή. Όσο το σύμπλεγμα θυμάται τον χαμένο κόμβο, θυμάται την παλιά ουρά και τους μη συγχρονισμένους καθρέφτες. Όταν ένα σύμπλεγμα λέει να ξεχάσει έναν χαμένο κόμβο, αυτή η ουρά ξεχνιέται επίσης. Τώρα πρέπει να το ανακοινώσουμε ξανά. Χάσαμε όλα τα δεδομένα, αν και είχαμε καθρέφτες με μερικά δεδομένα. Θα ήταν καλύτερα να μεταβείτε σε έναν μη συγχρονισμένο καθρέφτη!
Επομένως, ο χειροκίνητος συγχρονισμός (και η αποτυχία συγχρονισμού) σε συνδυασμό με ha-promote-on-failure=when-synced, κατά τη γνώμη μου, είναι αρκετά επικίνδυνο. Τα έγγραφα λένε ότι αυτή η επιλογή υπάρχει για την ασφάλεια των δεδομένων, αλλά είναι ένα δίκοπο μαχαίρι.
Επανεξισορρόπηση πλοιάρχων
Όπως υποσχεθήκαμε, επιστρέφουμε στο πρόβλημα της συγκέντρωσης όλων των κυρίων σε έναν ή περισσότερους κόμβους. Αυτό μπορεί να συμβεί ακόμη και ως αποτέλεσμα αναβάθμισης κυλιόμενου συμπλέγματος. Σε ένα σύμπλεγμα τριών κόμβων, όλες οι κύριες ουρές θα συγκεντρωθούν σε έναν ή δύο κόμβους.
Η επανεξισορρόπηση των κυρίων μπορεί να είναι προβληματική για δύο λόγους:
- Δεν υπάρχουν καλά εργαλεία για την επανεξισορρόπηση
- Συγχρονισμός ουράς
Υπάρχει τρίτο μέρος για επανεξισορρόπηση , το οποίο δεν υποστηρίζεται επίσημα. Σχετικά με τα πρόσθετα τρίτων στο εγχειρίδιο RabbitMQ : "Η προσθήκη παρέχει ορισμένα πρόσθετα εργαλεία διαμόρφωσης και αναφοράς, αλλά δεν υποστηρίζεται ούτε δοκιμάζεται από την ομάδα του RabbitMQ. Χρησιμοποιήστε τη με δική σας ευθύνη."
Υπάρχει ένα άλλο κόλπο για να μετακινήσετε την κύρια ουρά μέσω των πολιτικών HA. Το εγχειρίδιο αναφέρει για αυτό. Λειτουργεί ως εξής:
- Καταργεί όλους τους καθρέφτες χρησιμοποιώντας μια προσωρινή πολιτική με υψηλότερη προτεραιότητα από την υπάρχουσα πολιτική HA.
- Αλλάζει την προσωρινή πολιτική HA για χρήση της λειτουργίας "κόμβοι", καθορίζοντας τον κόμβο στον οποίο θα πρέπει να μετεγκατασταθεί η κύρια ουρά.
- Συγχρονίζει την ουρά για αναγκαστική μετεγκατάσταση.
- Αφού ολοκληρωθεί η μετεγκατάσταση, καταργείται η προσωρινή πολιτική. Η αρχική πολιτική HA τίθεται σε ισχύ και δημιουργείται ο απαιτούμενος αριθμός κατόπτρων.
Το μειονέκτημα είναι ότι αυτή η προσέγγιση μπορεί να μην λειτουργεί εάν έχετε μεγάλες ουρές ή αυστηρές απαιτήσεις πλεονασμού.
Τώρα ας δούμε πώς λειτουργούν τα συμπλέγματα RabbitMQ με κατατμήσεις δικτύου.
Απώλεια συνδεσιμότητας
Οι κόμβοι σε ένα κατανεμημένο σύστημα συνδέονται με συνδέσμους δικτύου και οι συνδέσεις δικτύου μπορούν και θα αποσυνδεθούν. Η συχνότητα των διακοπών εξαρτάται από την τοπική υποδομή ή την αξιοπιστία του επιλεγμένου νέφους. Σε κάθε περίπτωση, τα κατανεμημένα συστήματα θα πρέπει να μπορούν να τα χειριστούν. Για άλλη μια φορά βρισκόμαστε αντιμέτωποι με μια επιλογή μεταξύ διαθεσιμότητας και συνέπειας, και για άλλη μια φορά τα καλά νέα είναι ότι το RabbitMQ παρέχει και τα δύο (απλώς όχι ταυτόχρονα).
Με το RabbitMQ έχουμε δύο βασικές επιλογές:
- Επιτρέψτε το split-brain. Αυτό διασφαλίζει τη διαθεσιμότητα, αλλά μπορεί να οδηγήσει σε απώλεια δεδομένων.
- Απενεργοποιήστε τον λογικό διαχωρισμό. Μπορεί να οδηγήσει σε βραχυπρόθεσμη απώλεια διαθεσιμότητας ανάλογα με τον τρόπο σύνδεσης των πελατών στο σύμπλεγμα. Μπορεί επίσης να οδηγήσει σε πλήρη μη διαθεσιμότητα σε ένα σύμπλεγμα δύο κόμβων.
Τι είναι όμως η λογική διαίρεση; Αυτό συμβαίνει όταν ένα σύμπλεγμα χωρίζεται στα δύο λόγω απώλειας συνδέσεων δικτύου. Κάθε πλευρά του καθρέφτη προωθείται σε κύριο, έτσι ώστε κάθε ουρά να καταλήγει σε πολλούς κύριους.

Ρύζι. 17. Η κύρια ουρά και δύο καθρέφτες, το καθένα σε ξεχωριστό κόμβο. Στη συνέχεια παρουσιάζεται μια αποτυχία δικτύου και ένας καθρέφτης διαχωρίζεται. Ο διαχωρισμένος κόμβος βλέπει ότι οι άλλοι δύο έχουν πέσει και προωθεί τους καθρέφτες του στον κύριο. Τώρα έχουμε δύο κύριες ουρές, εγγράψιμες και αναγνώσιμες.
Εάν οι εκδότες στείλουν δεδομένα και στους δύο κύριους, θα καταλήξουμε με δύο αποκλίνοντα αντίγραφα της ουράς.
Οι διαφορετικοί τρόποι λειτουργίας του RabbitMQ παρέχουν είτε διαθεσιμότητα είτε συνέπεια.
Λειτουργία παράβλεψης (προεπιλογή)
Αυτή η λειτουργία παρέχει προσβασιμότητα. Μετά την απώλεια της συνοχής επέρχεται ένας λογικός διαχωρισμός. Μόλις αποκατασταθεί η συνδεσιμότητα, ο διαχειριστής πρέπει να αποφασίσει ποιο διαμέρισμα θα δώσει προτεραιότητα. Η χαμένη πλευρά θα επανεκκινηθεί και όλα τα συσσωρευμένα δεδομένα σε αυτήν την πλευρά θα χαθούν.

Ρύζι. 18. Τρεις εκδότες συνδέονται με τρεις μεσίτες. Εσωτερικά, το σύμπλεγμα δρομολογεί όλα τα αιτήματα στην κύρια ουρά στο Broker 2.
Τώρα χάνουμε το Broker 3. Βλέπει ότι άλλοι μεσίτες έχουν παραιτηθεί και προωθεί τον καθρέφτη του στον κύριο. Έτσι γίνεται η λογική διαίρεση.

Ρύζι. 19. Λογική διαίρεση (split-brain). Οι εγγραφές μπαίνουν σε δύο κύριες ουρές και τα δύο αντίγραφα αποκλίνουν.
Η συνοχή αποκαθίσταται, αλλά ο λογικός διαχωρισμός παραμένει. Ο διαχειριστής πρέπει να επιλέξει χειροκίνητα την πλευρά που χάνει. Στην παρακάτω περίπτωση, ο διαχειριστής κάνει επανεκκίνηση του Broker 3. Όλα τα μηνύματα που δεν κατάφερε να μεταδώσει χάνονται.

Ρύζι. 20. Ο διαχειριστής απενεργοποιεί το Broker 3.

Ρύζι. 21. Ο διαχειριστής ξεκινά το Broker 3 και ενώνεται στο σύμπλεγμα, χάνοντας τα μηνύματα που είχαν μείνει εκεί.
Κατά τη διάρκεια της απώλειας της συνδεσιμότητας και μετά την αποκατάστασή της, το σύμπλεγμα και αυτή η ουρά ήταν διαθέσιμα για ανάγνωση και γραφή.
Λειτουργία αυτόματης θεραπείας
Λειτουργεί παρόμοια με τη λειτουργία Ignore, με τη διαφορά ότι το ίδιο το σύμπλεγμα επιλέγει αυτόματα την πλευρά που χάνει μετά από μια διαίρεση και επανασύνδεση. Η χαμένη πλευρά επιστρέφει στο σύμπλεγμα κενή και η ουρά χάνει όλα τα μηνύματα που στάλθηκαν μόνο σε αυτήν την πλευρά.
Παύση λειτουργίας μειοψηφίας
Εάν δεν θέλουμε να επιτρέψουμε τη λογική κατάτμηση, τότε η μόνη μας επιλογή είναι να αρνηθούμε την ανάγνωση και τη γραφή στη μικρότερη πλευρά μετά το διαμέρισμα συμπλέγματος. Όταν ο μεσίτης βλέπει ότι βρίσκεται στη μικρότερη πλευρά, διακόπτει τις εργασίες, δηλαδή κλείνει όλες τις υπάρχουσες συνδέσεις και αρνείται τυχόν νέες. Μία φορά ανά δευτερόλεπτο ελέγχει για αποκατάσταση συνδεσιμότητας. Μόλις αποκατασταθεί η συνδεσιμότητα, συνεχίζει να λειτουργεί και εντάσσεται στο σύμπλεγμα.

Ρύζι. 22. Τρεις εκδότες συνδέονται με τρεις μεσίτες. Εσωτερικά, το σύμπλεγμα δρομολογεί όλα τα αιτήματα στην κύρια ουρά στο Broker 2.
Στη συνέχεια, οι Brokers 1 και 2 χωρίστηκαν από το Broker 3. Αντί να προωθήσει το mirror του σε master, το Broker 3 σταματά και γίνεται μη διαθέσιμο.

Ρύζι. 23. Ο Broker 3 διακόπτει τις λειτουργίες, αποσυνδέει όλους τους πελάτες και απορρίπτει αιτήματα σύνδεσης.
Μόλις αποκατασταθεί η συνδεσιμότητα, επιστρέφει στο σύμπλεγμα.
Ας δούμε ένα άλλο παράδειγμα όπου η κύρια ουρά βρίσκεται στο Broker 3.

Ρύζι. 24. Κύρια ουρά στο Broker 3.
Τότε συμβαίνει η ίδια απώλεια συνοχής. Το Broker 3 κάνει παύση όπως είναι στη μικρότερη πλευρά. Από την άλλη πλευρά, οι κόμβοι βλέπουν ότι το Broker 3 έχει πέσει, έτσι ο παλαιότερος καθρέφτης από τους Brokers 1 και 2 προωθείται σε master.

Ρύζι. 25. Μετάβαση στο Broker 2 όταν το Broker 3 δεν είναι διαθέσιμο.
Μόλις αποκατασταθεί η συνδεσιμότητα, το Broker 3 θα ενταχθεί στο σύμπλεγμα.

Ρύζι. 26. Το σύμπλεγμα έχει επιστρέψει στην κανονική λειτουργία.
Το σημαντικό πράγμα που πρέπει να καταλάβουμε εδώ είναι ότι έχουμε συνέπεια, αλλά μπορούμε επίσης να αποκτήσουμε προσβασιμότητα, αν Θα μεταφέρουμε με επιτυχία πελάτες στο μεγαλύτερο μέρος του τμήματος. Για τις περισσότερες περιπτώσεις, θα επέλεγα προσωπικά τη λειτουργία Pause Minority, αλλά εξαρτάται πραγματικά από τη συγκεκριμένη περίπτωση.
Για να διασφαλιστεί η διαθεσιμότητα, είναι σημαντικό να διασφαλιστεί ότι οι πελάτες μπορούν να συνδεθούν με επιτυχία στον κόμβο. Ας εξετάσουμε τις επιλογές μας.
Εξασφάλιση συνδεσιμότητας πελατών
Έχουμε πολλές επιλογές για το πώς να κατευθύνουμε τους πελάτες στο κύριο μέρος του συμπλέγματος ή σε κόμβους εργασίας (μετά από αποτυχία ενός κόμβου) μετά την απώλεια της συνδεσιμότητας. Αρχικά, ας θυμηθούμε ότι μια συγκεκριμένη ουρά φιλοξενείται σε έναν συγκεκριμένο κόμβο, αλλά η δρομολόγηση και οι πολιτικές αναπαράγονται σε όλους τους κόμβους. Οι πελάτες μπορούν να συνδεθούν σε οποιονδήποτε κόμβο και η εσωτερική δρομολόγηση θα τους κατευθύνει εκεί που πρέπει να πάνε. Αλλά όταν ένας κόμβος τίθεται σε παύση, απορρίπτει τις συνδέσεις, επομένως οι πελάτες πρέπει να συνδεθούν σε έναν άλλο κόμβο. Εάν ο κόμβος έχει πέσει, δεν μπορεί να κάνει καθόλου.
Οι επιλογές μας:
- Η πρόσβαση στο σύμπλεγμα γίνεται μέσω ενός εξισορροπητή φορτίου, ο οποίος απλώς περιηγείται στους κόμβους και οι πελάτες προσπαθούν να συνδεθούν ξανά μέχρι να πετύχουν. Εάν ένας κόμβος είναι εκτός λειτουργίας ή σε παύση, οι προσπάθειες σύνδεσης με αυτόν τον κόμβο θα αποτύχουν, αλλά οι επόμενες προσπάθειες θα πάνε σε άλλους διακομιστές (με κυκλικό τρόπο). Αυτό είναι κατάλληλο για βραχυπρόθεσμη απώλεια συνδεσιμότητας ή διακοπή λειτουργίας διακομιστή που θα επανέλθει γρήγορα.
- Αποκτήστε πρόσβαση στο σύμπλεγμα μέσω του εξισορροπητή φορτίου και αφαιρέστε τους κόμβους που έχουν τεθεί σε παύση/αποτυχία από τη λίστα μόλις εντοπιστούν. Εάν το κάνουμε αυτό γρήγορα και εάν οι πελάτες μπορούν να επαναλάβουν τη σύνδεση, τότε θα έχουμε συνεχή διαθεσιμότητα.
- Δώστε σε κάθε πελάτη μια λίστα με όλους τους κόμβους και ο πελάτης επιλέγει τυχαία έναν από αυτούς κατά τη σύνδεση. Εάν εμφανιστεί σφάλμα κατά την προσπάθεια σύνδεσης, μεταβαίνει στον επόμενο κόμβο της λίστας μέχρι να συνδεθεί.
- Καταργήστε την επισκεψιμότητα από έναν κόμβο που έχει τεθεί εκτός λειτουργίας/παύση χρησιμοποιώντας DNS. Αυτό γίνεται χρησιμοποιώντας μικρό TTL.
Ευρήματα
Η ομαδοποίηση RabbitMQ έχει τα δικά της πλεονεκτήματα και μειονεκτήματα. Τα πιο σοβαρά μειονεκτήματα είναι ότι:
- Όταν ενώνονται σε ένα σύμπλεγμα, οι κόμβοι απορρίπτουν τα δεδομένα τους.
- Ο αποκλεισμός του συγχρονισμού έχει ως αποτέλεσμα τη μη διαθεσιμότητα της ουράς.
Όλες οι δύσκολες αποφάσεις προκύπτουν από αυτά τα δύο χαρακτηριστικά της αρχιτεκτονικής. Εάν το RabbitMQ μπορούσε να διατηρήσει δεδομένα σε όλες τις επανασυνδέσεις συμπλέγματος, ο συγχρονισμός θα ήταν ταχύτερος. Αν είχε τη δυνατότητα συγχρονισμού χωρίς αποκλεισμό, θα υποστήριζε καλύτερα μεγάλες ουρές. Η διόρθωση αυτών των δύο προβλημάτων θα βελτίωνε σημαντικά την απόδοση του RabbitMQ ως τεχνολογίας ανταλλαγής μηνυμάτων με ανοχή σε σφάλματα και εξαιρετικά διαθέσιμη. Θα δίσταζα να προτείνω το RabbitMQ με ομαδοποίηση στις ακόλουθες περιπτώσεις:
- Αναξιόπιστο δίκτυο.
- Αναξιόπιστη αποθήκευση.
- Πολύ μεγάλες ουρές.
Όσον αφορά τις ρυθμίσεις υψηλής διαθεσιμότητας, λάβετε υπόψη τα εξής:
ha-promote-on-failure=alwaysha-sync-mode=manualcluster_partition_handling=ignore(ήautoheal)- επίμονα μηνύματα
- βεβαιωθείτε ότι οι πελάτες συνδέονται στον ενεργό κόμβο όταν ένας κόμβος πέφτει
Για συνέπεια (ασφάλεια δεδομένων), λάβετε υπόψη τις ακόλουθες ρυθμίσεις:
- Επιβεβαιώσεις εκδότη και μη αυτόματες επιβεβαιώσεις από την πλευρά του καταναλωτή
ha-promote-on-failure=when-synced, εάν οι εκδότες μπορούν να δοκιμάσουν ξανά αργότερα και εάν έχετε πολύ αξιόπιστο χώρο αποθήκευσης! Διαφορετικά, βάλτε το=always.ha-sync-mode=automatic(αλλά για μεγάλες ανενεργές ουρές μπορεί να απαιτείται χειροκίνητη λειτουργία. Επίσης, εξετάστε εάν η μη διαθεσιμότητα θα οδηγήσει σε χαμένα μηνύματα)- Παύση λειτουργίας μειοψηφίας
- επίμονα μηνύματα
Δεν έχουμε καλύψει ακόμα όλα τα θέματα ανοχής σφαλμάτων και υψηλής διαθεσιμότητας. για παράδειγμα, πώς να εκτελείτε διαχειριστικές διαδικασίες (όπως κυλιόμενες ενημερώσεις) με ασφάλεια. Πρέπει επίσης να μιλήσουμε για την ομοσπονδία και το πρόσθετο Shovel.
Αν μου έχει διαφύγει κάτι άλλο, ενημερώστε με.
Δείτε επίσης το δικό μου , όπου προκαλώ τον όλεθρο σε ένα σύμπλεγμα RabbitMQ χρησιμοποιώντας Docker και Blockade για να δοκιμάσω ορισμένα από τα σενάρια απώλειας μηνυμάτων που περιγράφονται σε αυτό το άρθρο.
Προηγούμενα άρθρα της σειράς:
Νο. 1 -
Νο. 2 -
Νο. 3 -
Πηγή: www.habr.com
