Κατανόηση των μεσιτών μηνυμάτων. Μαθαίνοντας τους μηχανισμούς των μηνυμάτων με το ActiveMQ και τον Kafka. Κεφάλαιο 3. Κάφκα

Συνέχεια της μετάφρασης ενός μικρού βιβλίου:
Κατανόηση Message Brokers
συγγραφέας: Jakub Korab, εκδότης: O'Reilly Media, Inc., ημερομηνία δημοσίευσης: Ιούνιος 2017, ISBN: 9781492049296.

Προηγούμενο μεταφρασμένο μέρος: Κατανόηση των μεσιτών μηνυμάτων. Μαθαίνοντας τους μηχανισμούς των μηνυμάτων με το ActiveMQ και τον Kafka. κεφάλαιο 1 Εισαγωγή

ΚΕΦΑΛΑΙΟ 3

Κάφκα

Το Kafka αναπτύχθηκε από το LinkedIn για να παρακάμψει ορισμένους από τους περιορισμούς των παραδοσιακών μεσιτών μηνυμάτων και να αποφύγει τη δημιουργία πολλών μεσιτών μηνυμάτων για διαφορετικές αλληλεπιδράσεις από σημείο σε σημείο, κάτι που περιγράφεται σε αυτό το βιβλίο στην ενότητα "Κλιμάκωση και μείωση" στη σελίδα 28 Περιπτώσεις χρήσης Το LinkedIn έχει βασιστεί σε μεγάλο βαθμό στη μονόδρομη απορρόφηση πολύ μεγάλων ποσοτήτων δεδομένων, όπως κλικ σε σελίδες και αρχεία καταγραφής πρόσβασης, ενώ εξακολουθεί να επιτρέπει τη χρήση αυτών των δεδομένων από πολλά συστήματα χωρίς να επηρεάζεται η παραγωγικότητα των παραγωγών ή άλλων καταναλωτών. Στην πραγματικότητα, ο λόγος που υπάρχει ο Κάφκα είναι για να αποκτήσει το είδος της αρχιτεκτονικής ανταλλαγής μηνυμάτων που περιγράφει η Universal Data Pipeline.

Δεδομένου αυτού του απώτερου στόχου, προέκυψαν φυσικά και άλλες απαιτήσεις. Ο Κάφκα πρέπει:

  • Να είστε εξαιρετικά γρήγοροι
  • Παρέχετε περισσότερο εύρος ζώνης όταν εργάζεστε με μηνύματα
  • Υποστήριξη μοντέλων Publisher-Subscriber και Point-to-Point
  • Μην επιβραδύνετε με την προσθήκη καταναλωτών. Για παράδειγμα, η απόδοση τόσο της ουράς όσο και του θέματος στο ActiveMQ υποβαθμίζεται καθώς αυξάνεται ο αριθμός των καταναλωτών στον προορισμό.
  • Να είναι οριζόντια κλιμακωτός. εάν ένας μεσίτης που επιμένει στα μηνύματα μπορεί να το κάνει μόνο με τη μέγιστη ταχύτητα δίσκου, τότε είναι λογικό να υπερβείτε μια μόνο περίπτωση μεσίτη για να αυξήσετε την απόδοση
  • Περιορίστε την πρόσβαση στην αποθήκευση και την εκ νέου ανάκτηση μηνυμάτων

Για να τα επιτύχει όλα αυτά, ο Κάφκα υιοθέτησε μια αρχιτεκτονική που επαναπροσδιόρισε τους ρόλους και τις ευθύνες των πελατών και των μεσιτών μηνυμάτων. Το μοντέλο JMS είναι πολύ προσανατολισμένο στον μεσίτη, όπου ο μεσίτης είναι υπεύθυνος για τη διανομή μηνυμάτων και οι πελάτες πρέπει να ανησυχούν μόνο για την αποστολή και λήψη μηνυμάτων. Ο Κάφκα, από την άλλη πλευρά, είναι πελατοκεντρικός, με τον πελάτη να αποκτά πολλά από τα χαρακτηριστικά ενός παραδοσιακού μεσίτη, όπως η δίκαιη διανομή σχετικών μηνυμάτων στους καταναλωτές, με αντάλλαγμα έναν εξαιρετικά γρήγορο και επεκτάσιμο μεσίτη. Για άτομα που έχουν εργαστεί με παραδοσιακά συστήματα ανταλλαγής μηνυμάτων, η συνεργασία με τον Κάφκα απαιτεί μια θεμελιώδη αλλαγή γνώμης.
Αυτή η κατεύθυνση μηχανικής οδήγησε στη δημιουργία μιας υποδομής ανταλλαγής μηνυμάτων ικανή να αυξήσει την απόδοση κατά πολλές τάξεις μεγέθους σε σύγκριση με έναν συμβατικό μεσίτη. Όπως θα δούμε, αυτή η προσέγγιση συνοδεύεται από συμβιβασμούς, πράγμα που σημαίνει ότι το Kafka δεν είναι κατάλληλο για ορισμένους τύπους φόρτου εργασίας και εγκατεστημένο λογισμικό.

Μοντέλο Ενοποιημένου Προορισμού

Για να εκπληρώσει τις απαιτήσεις που περιγράφονται παραπάνω, ο Kafka συνδύασε τη δημοσίευση-συνδρομή και την ανταλλαγή μηνυμάτων από σημείο σε σημείο κάτω από ένα είδος προορισμού − θέμα. Αυτό προκαλεί σύγχυση στους ανθρώπους που έχουν εργαστεί με συστήματα ανταλλαγής μηνυμάτων, όπου η λέξη "θέμα" αναφέρεται σε έναν μηχανισμό εκπομπής από τον οποίο (από το θέμα) η ανάγνωση δεν είναι ανθεκτική. Τα θέματα του Κάφκα θα πρέπει να θεωρούνται ως υβριδικός τύπος προορισμού, όπως ορίζεται στην εισαγωγή αυτού του βιβλίου.

Για το υπόλοιπο αυτού του κεφαλαίου, εκτός εάν δηλώνουμε ρητά διαφορετικά, ο όρος «θέμα» θα αναφέρεται σε ένα θέμα του Κάφκα.

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

Οι όροι "ημερολόγιο" και "δείκτης" δεν εμφανίζονται στο Τεκμηρίωση Κάφκα. Αυτοί οι γνωστοί όροι χρησιμοποιούνται εδώ για να βοηθήσουν στην κατανόηση.

Αυτό το μοντέλο είναι εντελώς διαφορετικό από το ActiveMQ, όπου τα μηνύματα από όλες τις ουρές αποθηκεύονται στο ίδιο αρχείο καταγραφής και ο μεσίτης επισημαίνει τα μηνύματα ως διαγραμμένα μετά την ανάγνωσή τους.
Ας σκάψουμε τώρα λίγο πιο βαθιά και ας δούμε το αρχείο καταγραφής θεμάτων με περισσότερες λεπτομέρειες.
Το αρχείο καταγραφής Kafka αποτελείται από πολλά διαμερίσματα (Εικόνα-3 1). Ο Κάφκα εγγυάται αυστηρή παραγγελία σε κάθε διαμέρισμα. Αυτό σημαίνει ότι τα μηνύματα που είναι γραμμένα στο διαμέρισμα με συγκεκριμένη σειρά θα διαβάζονται με την ίδια σειρά. Κάθε διαμέρισμα υλοποιείται ως κυλιόμενο αρχείο καταγραφής που περιέχει ένα υποσύνολο (υποσύνολο) όλων των μηνυμάτων που αποστέλλονται στο θέμα από τους παραγωγούς του. Το θέμα που δημιουργήθηκε περιέχει, από προεπιλογή, ένα διαμέρισμα. Η ιδέα των χωρισμάτων είναι η κεντρική ιδέα του Κάφκα για οριζόντια κλιμάκωση.

Κατανόηση των μεσιτών μηνυμάτων. Μαθαίνοντας τους μηχανισμούς των μηνυμάτων με το ActiveMQ και τον Kafka. Κεφάλαιο 3. Κάφκα
Εικόνα 3-1. Χωρίσματα Κάφκα

Όταν ένας παραγωγός στέλνει ένα μήνυμα σε ένα θέμα του Κάφκα, αποφασίζει σε ποιο διαμέρισμα θα στείλει το μήνυμα. Θα το δούμε πιο αναλυτικά αργότερα.

Ανάγνωση μηνυμάτων

Ο πελάτης που θέλει να διαβάσει τα μηνύματα διαχειρίζεται έναν επώνυμο δείκτη που ονομάζεται ομάδα καταναλωτών, που παραπέμπει σε αντισταθμίζεται μηνύματα στο διαμέρισμα. Η μετατόπιση είναι μια σταδιακή θέση που ξεκινά από το 0 στην αρχή ενός διαμερίσματος. Αυτή η ομάδα καταναλωτών, που αναφέρεται στο API μέσω του group_id που ορίζεται από το χρήστη, αντιστοιχεί σε ένας λογικός καταναλωτής ή σύστημα.

Τα περισσότερα συστήματα ανταλλαγής μηνυμάτων διαβάζουν δεδομένα από τον προορισμό χρησιμοποιώντας πολλαπλές παρουσίες και νήματα για την παράλληλη επεξεργασία μηνυμάτων. Έτσι, θα υπάρχουν συνήθως πολλές περιπτώσεις καταναλωτών που μοιράζονται την ίδια ομάδα καταναλωτών.

Το πρόβλημα της ανάγνωσης μπορεί να αναπαρασταθεί ως εξής:

  • Το θέμα έχει πολλαπλές κατατμήσεις
  • Πολλές ομάδες καταναλωτών μπορούν να χρησιμοποιούν ένα θέμα ταυτόχρονα
  • Μια ομάδα καταναλωτών μπορεί να έχει πολλαπλές ξεχωριστές περιπτώσεις

Αυτό είναι ένα μη τετριμμένο πρόβλημα πολλά-προς-πολλά. Για να κατανοήσουμε πώς ο Κάφκα χειρίζεται τις σχέσεις μεταξύ ομάδων καταναλωτών, παρουσιών καταναλωτών και διαμερισμάτων, ας δούμε μια σειρά προοδευτικά πιο περίπλοκων σεναρίων ανάγνωσης.

Καταναλωτές και ομάδες καταναλωτών

Ας πάρουμε ως σημείο εκκίνησης ένα θέμα με ένα διαμέρισμα (Εικόνα-3 2).

Κατανόηση των μεσιτών μηνυμάτων. Μαθαίνοντας τους μηχανισμούς των μηνυμάτων με το ActiveMQ και τον Kafka. Κεφάλαιο 3. Κάφκα
Εικόνα 3-2. Ο καταναλωτής διαβάζει από το διαμέρισμα

Όταν ένα στιγμιότυπο καταναλωτή συνδέεται με το δικό του group_id σε αυτό το θέμα, του εκχωρείται ένα διαμέρισμα ανάγνωσης και μια μετατόπιση σε αυτό το διαμέρισμα. Η θέση αυτής της μετατόπισης μπορεί να διαμορφωθεί στον υπολογιστή-πελάτη ως δείκτης στην πιο πρόσφατη θέση (νεότερο μήνυμα) ή στην παλαιότερη θέση (παλαιότερο μήνυμα). Ο καταναλωτής ζητά (δημοσκοπήσεις) μηνύματα από το θέμα, με αποτέλεσμα να διαβάζονται διαδοχικά από το αρχείο καταγραφής.
Η θέση μετατόπισης δεσμεύεται τακτικά στον Κάφκα και αποθηκεύεται ως μηνύματα σε ένα εσωτερικό θέμα _αντισταθμίσεις_καταναλωτή. Τα αναγνωσμένα μηνύματα εξακολουθούν να μην διαγράφονται, σε αντίθεση με έναν κανονικό μεσίτη, και ο πελάτης μπορεί να επαναφέρει τη μετατόπιση για να επεξεργαστεί ξανά τα μηνύματα που έχουν προβληθεί.

Όταν ένας δεύτερος λογικός καταναλωτής συνδέεται χρησιμοποιώντας ένα διαφορετικό group_id, διαχειρίζεται έναν δεύτερο δείκτη που είναι ανεξάρτητος από τον πρώτο (Εικόνα-3 3). Έτσι, ένα θέμα Kafka λειτουργεί σαν μια ουρά όπου υπάρχει ένας καταναλωτής και σαν ένα κανονικό θέμα δημοσίευσης-εγγραφής (pub-sub) στο οποίο εγγράφονται πολλοί καταναλωτές, με το πρόσθετο πλεονέκτημα ότι όλα τα μηνύματα αποθηκεύονται και μπορούν να υποβληθούν σε επεξεργασία πολλές φορές.

Κατανόηση των μεσιτών μηνυμάτων. Μαθαίνοντας τους μηχανισμούς των μηνυμάτων με το ActiveMQ και τον Kafka. Κεφάλαιο 3. Κάφκα
Εικόνα 3-3. Δύο καταναλωτές σε διαφορετικές ομάδες καταναλωτών διαβάζουν από το ίδιο διαμέρισμα

Καταναλωτές σε μια ομάδα καταναλωτών

Όταν μια παρουσία καταναλωτή διαβάζει δεδομένα από ένα διαμέρισμα, έχει τον πλήρη έλεγχο του δείκτη και επεξεργάζεται τα μηνύματα όπως περιγράφεται στην προηγούμενη ενότητα.
Εάν πολλές περιπτώσεις καταναλωτών συνδέθηκαν με το ίδιο group_id σε ένα θέμα με ένα διαμέρισμα, τότε η παρουσία που συνδέθηκε τελευταία θα έχει τον έλεγχο του δείκτη και από εκείνη τη στιγμή θα λαμβάνει όλα τα μηνύματα (Εικόνα-3 4).

Κατανόηση των μεσιτών μηνυμάτων. Μαθαίνοντας τους μηχανισμούς των μηνυμάτων με το ActiveMQ και τον Kafka. Κεφάλαιο 3. Κάφκα
Εικόνα 3-4. Δύο καταναλωτές στην ίδια ομάδα καταναλωτών διαβάζουν από το ίδιο διαμέρισμα

Αυτός ο τρόπος επεξεργασίας, στον οποίο ο αριθμός των περιπτώσεων καταναλωτή υπερβαίνει τον αριθμό των κατατμήσεων, μπορεί να θεωρηθεί ως ένα είδος αποκλειστικού καταναλωτή. Αυτό μπορεί να είναι χρήσιμο εάν χρειάζεστε ομαδοποίηση "ενεργού-παθητικού" (ή "ζεστό-ζεστό") των παρουσιών καταναλωτών σας, αν και η παράλληλη εκτέλεση πολλών καταναλωτών ("ενεργή-ενεργή" ή "καυτή-ζεστή") είναι πολύ πιο τυπική από καταναλωτές, σε αναμονή.

Αυτή η συμπεριφορά διανομής μηνυμάτων που περιγράφεται παραπάνω μπορεί να είναι εκπληκτική σε σύγκριση με το πώς συμπεριφέρεται μια κανονική ουρά JMS. Σε αυτό το μοντέλο, τα μηνύματα που αποστέλλονται στην ουρά θα κατανέμονται ομοιόμορφα μεταξύ των δύο καταναλωτών.

Τις περισσότερες φορές, όταν δημιουργούμε πολλαπλές περιπτώσεις καταναλωτών, το κάνουμε είτε για να επεξεργαστούμε μηνύματα παράλληλα, είτε για να αυξήσουμε την ταχύτητα ανάγνωσης είτε για να αυξήσουμε τη σταθερότητα της διαδικασίας ανάγνωσης. Εφόσον μόνο μία παρουσία καταναλωτή μπορεί να διαβάζει δεδομένα από ένα διαμέρισμα κάθε φορά, πώς επιτυγχάνεται αυτό στον Κάφκα;

Ένας τρόπος για να το κάνετε αυτό είναι να χρησιμοποιήσετε μια μόνο παρουσία καταναλωτή για να διαβάσετε όλα τα μηνύματα και να τα μεταφέρετε στο νήμα. Ενώ αυτή η προσέγγιση αυξάνει την απόδοση της επεξεργασίας, αυξάνει την πολυπλοκότητα της λογικής του καταναλωτή και δεν κάνει τίποτα για να αυξήσει την ευρωστία του συστήματος ανάγνωσης. Εάν ένα αντίγραφο του καταναλωτή πέσει λόγω διακοπής ρεύματος ή παρόμοιου συμβάντος, τότε η αφαίρεση σταματά.

Ο κανονικός τρόπος για να λυθεί αυτό το πρόβλημα στον Κάφκα είναι η χρήση του βОπερισσότερα διαμερίσματα.

Διαμέριση

Οι κατατμήσεις είναι ο κύριος μηχανισμός για τον παραλληλισμό της ανάγνωσης και την κλιμάκωση ενός θέματος πέρα ​​από το εύρος ζώνης μιας μεμονωμένης παρουσίας μεσίτη. Για να το κατανοήσουμε καλύτερα αυτό, ας εξετάσουμε μια κατάσταση όπου υπάρχει ένα θέμα με δύο διαμερίσματα και ένας καταναλωτής έχει εγγραφεί σε αυτό το θέμα (Εικόνα-3 5).

Κατανόηση των μεσιτών μηνυμάτων. Μαθαίνοντας τους μηχανισμούς των μηνυμάτων με το ActiveMQ και τον Kafka. Κεφάλαιο 3. Κάφκα
Εικόνα 3-5. Ένας καταναλωτής διαβάζει από πολλαπλά διαμερίσματα

Σε αυτό το σενάριο, ο καταναλωτής έχει τον έλεγχο των δεικτών που αντιστοιχούν στο group_id του και στα δύο διαμερίσματα και αρχίζει να διαβάζει μηνύματα και από τα δύο διαμερίσματα.
Όταν προστίθεται ένας επιπλέον καταναλωτής για το ίδιο group_id σε αυτό το θέμα, ο Kafka ανακατανέμει ένα από τα διαμερίσματα από τον πρώτο στον δεύτερο καταναλωτή. Μετά από αυτό, κάθε παρουσία του καταναλωτή θα διαβάζει από ένα διαμέρισμα του θέματος (Εικόνα-3 6).

Για να διασφαλίσετε ότι τα μηνύματα επεξεργάζονται παράλληλα σε 20 νήματα, χρειάζεστε τουλάχιστον 20 κατατμήσεις. Εάν υπάρχουν λιγότερα διαμερίσματα, θα μείνετε με καταναλωτές που δεν έχουν τίποτα να εργαστούν, όπως περιγράφηκε προηγουμένως στη συζήτηση των αποκλειστικών καταναλωτών.

Κατανόηση των μεσιτών μηνυμάτων. Μαθαίνοντας τους μηχανισμούς των μηνυμάτων με το ActiveMQ και τον Kafka. Κεφάλαιο 3. Κάφκα
Εικόνα 3-6. Δύο καταναλωτές στην ίδια ομάδα καταναλωτών διαβάζουν από διαφορετικά διαμερίσματα

Αυτό το σχήμα μειώνει σημαντικά την πολυπλοκότητα του μεσίτη Kafka σε σύγκριση με τη διανομή μηνυμάτων που απαιτείται για τη διατήρηση της ουράς JMS. Εδώ δεν χρειάζεται να ανησυχείτε για τα ακόλουθα σημεία:

  • Ποιος καταναλωτής θα πρέπει να λάβει το επόμενο μήνυμα, με βάση την κατανομή κυκλικής ανάλυσης, την τρέχουσα χωρητικότητα των buffers prefetch ή τα προηγούμενα μηνύματα (όπως για τις ομάδες μηνυμάτων JMS).
  • Ποια μηνύματα αποστέλλονται σε ποιους καταναλωτές και αν θα πρέπει να παραδοθούν εκ νέου σε περίπτωση αποτυχίας.

Το μόνο που έχει να κάνει ο μεσίτης Kafka είναι να περνά μηνύματα διαδοχικά στον καταναλωτή όταν ο τελευταίος τα ζητήσει.

Ωστόσο, οι απαιτήσεις για τον παραλληλισμό της διόρθωσης και την εκ νέου αποστολή των αποτυχημένων μηνυμάτων δεν εξαφανίζονται - η ευθύνη για αυτά απλώς περνά από τον μεσίτη στον πελάτη. Αυτό σημαίνει ότι πρέπει να ληφθούν υπόψη στον κωδικό σας.

Αποστολή μηνυμάτων

Είναι ευθύνη του παραγωγού αυτού του μηνύματος να αποφασίσει σε ποιο διαμέρισμα θα στείλει ένα μήνυμα. Για να κατανοήσουμε τον μηχανισμό με τον οποίο γίνεται αυτό, πρέπει πρώτα να εξετάσουμε τι ακριβώς στέλνουμε στην πραγματικότητα.

Ενώ στο JMS χρησιμοποιούμε μια δομή μηνυμάτων με μεταδεδομένα (κεφαλίδες και ιδιότητες) και ένα σώμα που περιέχει το ωφέλιμο φορτίο (ωφέλιμο φορτίο), στον Κάφκα το μήνυμα είναι ζεύγος "κλειδί-τιμή". Το ωφέλιμο φορτίο του μηνύματος αποστέλλεται ως τιμή. Το κλειδί, από την άλλη πλευρά, χρησιμοποιείται κυρίως για διαχωρισμό και πρέπει να περιέχει συγκεκριμένο κλειδί επιχειρηματικής λογικήςγια να τοποθετήσετε σχετικά μηνύματα στο ίδιο διαμέρισμα.

Στο Κεφάλαιο 2, συζητήσαμε το σενάριο διαδικτυακών στοιχημάτων όπου τα σχετικά γεγονότα πρέπει να διεκπεραιωθούν με τη σειρά από έναν μόνο καταναλωτή:

  1. Ο λογαριασμός χρήστη έχει ρυθμιστεί.
  2. Τα χρήματα πιστώνονται στον λογαριασμό.
  3. Γίνεται ένα στοίχημα που αποσύρει χρήματα από τον λογαριασμό.

Εάν κάθε συμβάν είναι ένα μήνυμα που δημοσιεύεται σε ένα θέμα, τότε το φυσικό κλειδί θα είναι το αναγνωριστικό λογαριασμού.
Όταν ένα μήνυμα αποστέλλεται χρησιμοποιώντας το Kafka Producer API, μεταβιβάζεται σε μια συνάρτηση κατάτμησης η οποία, δεδομένου του μηνύματος και της τρέχουσας κατάστασης του συμπλέγματος Kafka, επιστρέφει το αναγνωριστικό του διαμερίσματος στο οποίο πρέπει να σταλεί το μήνυμα. Αυτή η δυνατότητα υλοποιείται σε Java μέσω της διεπαφής Partitioner.

Αυτή η διεπαφή μοιάζει με αυτό:

interface Partitioner {
    int partition(String topic,
        Object key, byte[] keyBytes, Object value, byte[] valueBytes, Cluster cluster);
}

Η υλοποίηση του Partitioner χρησιμοποιεί τον προεπιλεγμένο αλγόριθμο κατακερματισμού γενικής χρήσης πάνω από το κλειδί για τον προσδιορισμό του διαμερίσματος ή το round-robin εάν δεν έχει καθοριστεί κλειδί. Αυτή η προεπιλεγμένη τιμή λειτουργεί καλά στις περισσότερες περιπτώσεις. Ωστόσο, στο μέλλον θα θέλετε να γράψετε το δικό σας.

Γράψτε τη δική σας στρατηγική κατάτμησης

Ας δούμε ένα παράδειγμα όπου θέλετε να στείλετε μεταδεδομένα μαζί με το ωφέλιμο φορτίο του μηνύματος. Το ωφέλιμο φορτίο στο παράδειγμά μας είναι μια οδηγία για να κάνετε κατάθεση στον λογαριασμό του παιχνιδιού. Μια εντολή είναι κάτι για το οποίο θα θέλαμε να εγγυηθούμε ότι δεν θα τροποποιηθεί κατά τη μετάδοση και θέλουμε να είμαστε σίγουροι ότι μόνο ένα αξιόπιστο σύστημα ανάντη μπορεί να εκκινήσει αυτήν την εντολή. Σε αυτήν την περίπτωση, τα συστήματα αποστολής και λήψης συμφωνούν για τη χρήση υπογραφής για τον έλεγχο ταυτότητας του μηνύματος.
Στο κανονικό JMS, ορίζουμε απλώς μια ιδιότητα "υπογραφή μηνύματος" και την προσθέτουμε στο μήνυμα. Ωστόσο, ο Κάφκα δεν μας παρέχει έναν μηχανισμό για τη μετάδοση μεταδεδομένων, μόνο ένα κλειδί και μια τιμή.

Δεδομένου ότι η τιμή είναι ένα ωφέλιμο φορτίο τραπεζικής μεταφοράς του οποίου η ακεραιότητα θέλουμε να διατηρήσουμε, δεν έχουμε άλλη επιλογή από το να ορίσουμε τη δομή δεδομένων που θα χρησιμοποιήσουμε στο κλειδί. Αν υποθέσουμε ότι χρειαζόμαστε ένα αναγνωριστικό λογαριασμού για την κατάτμηση, καθώς όλα τα μηνύματα που σχετίζονται με έναν λογαριασμό πρέπει να υποβληθούν σε επεξεργασία με τη σειρά, θα καταλήξουμε στην ακόλουθη δομή JSON:

{
  "signature": "541661622185851c248b41bf0cea7ad0",
  "accountId": "10007865234"
}

Επειδή η τιμή της υπογραφής θα ποικίλλει ανάλογα με το ωφέλιμο φορτίο, η προεπιλεγμένη στρατηγική κατακερματισμού της διεπαφής Partitioner δεν θα ομαδοποιεί αξιόπιστα τα σχετικά μηνύματα. Επομένως, θα χρειαστεί να γράψουμε τη δική μας στρατηγική που θα αναλύει αυτό το κλειδί και θα διαμερίζει την τιμή accountId.

Το Kafka περιλαμβάνει αθροίσματα ελέγχου για την ανίχνευση φθοράς των μηνυμάτων στο κατάστημα και διαθέτει ένα πλήρες σύνολο χαρακτηριστικών ασφαλείας. Παρόλα αυτά, ορισμένες φορές εμφανίζονται απαιτήσεις για τον κλάδο, όπως η παραπάνω.

Η στρατηγική κατάτμησης του χρήστη πρέπει να διασφαλίζει ότι όλα τα σχετικά μηνύματα καταλήγουν στο ίδιο διαμέρισμα. Αν και αυτό φαίνεται απλό, η απαίτηση μπορεί να περιπλέκεται από τη σημασία της παραγγελίας σχετικών μηνυμάτων και το πόσο σταθερός είναι ο αριθμός των κατατμήσεων σε ένα θέμα.

Ο αριθμός των κατατμήσεων σε ένα θέμα μπορεί να αλλάξει με την πάροδο του χρόνου, καθώς μπορούν να προστεθούν εάν η επισκεψιμότητα υπερβαίνει τις αρχικές προσδοκίες. Έτσι, τα κλειδιά μηνυμάτων μπορούν να συσχετιστούν με το διαμέρισμα στο οποίο στάλθηκαν αρχικά, υποδηλώνοντας ένα κομμάτι κατάστασης που θα μοιραστεί μεταξύ των στιγμιότυπων παραγωγών.

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

Σκεφτείτε την απαίτηση για αναπαραγωγή δεδομένων μεταξύ συστάδων Κάφκα σε διαφορετικές γεωγραφικές τοποθεσίες. Για το σκοπό αυτό, ο Kafka συνοδεύεται από ένα εργαλείο γραμμής εντολών που ονομάζεται MirrorMaker, το οποίο χρησιμοποιείται για την ανάγνωση μηνυμάτων από ένα σύμπλεγμα και τη μεταφορά τους σε άλλο.

Το MirrorMaker πρέπει να κατανοήσει τα κλειδιά του αναπαραγόμενου θέματος για να διατηρεί τη σχετική τάξη μεταξύ των μηνυμάτων κατά την αναπαραγωγή μεταξύ συμπλεγμάτων, καθώς ο αριθμός των κατατμήσεων για αυτό το θέμα μπορεί να μην είναι ο ίδιος σε δύο συμπλέγματα.

Οι προσαρμοσμένες στρατηγικές διαμερισμάτων είναι σχετικά σπάνιες, καθώς ο προεπιλεγμένος κατακερματισμός ή το round robin λειτουργούν καλά στα περισσότερα σενάρια. Ωστόσο, εάν χρειάζεστε ισχυρές εγγυήσεις παραγγελίας ή χρειάζεται να εξαγάγετε μεταδεδομένα από ωφέλιμα φορτία, τότε η κατάτμηση είναι κάτι που θα πρέπει να ρίξετε μια πιο προσεκτική ματιά.

Τα οφέλη επεκτασιμότητας και απόδοσης του Kafka προέρχονται από τη μετατόπιση ορισμένων από τις ευθύνες του παραδοσιακού μεσίτη στον πελάτη. Σε αυτή την περίπτωση, λαμβάνεται απόφαση να διανεμηθούν δυνητικά σχετικά μηνύματα μεταξύ πολλών καταναλωτών που εργάζονται παράλληλα.

Οι μεσίτες JMS πρέπει επίσης να αντιμετωπίσουν τέτοιες απαιτήσεις. Είναι ενδιαφέρον ότι ο μηχανισμός για την αποστολή σχετικών μηνυμάτων στον ίδιο καταναλωτή, που υλοποιείται μέσω των ομάδων μηνυμάτων JMS (μια παραλλαγή της στρατηγικής σταθερής εξισορρόπησης φορτίου (SLB)), απαιτεί επίσης από τον αποστολέα να επισημαίνει τα μηνύματα ως σχετικά. Στην περίπτωση του JMS, ο μεσίτης είναι υπεύθυνος για την αποστολή αυτής της ομάδας σχετικών μηνυμάτων σε έναν από τους πολλούς καταναλωτή και τη μεταβίβαση της ιδιοκτησίας της ομάδας σε περίπτωση που ο καταναλωτής πέσει.

Συμφωνίες παραγωγών

Η κατάτμηση δεν είναι το μόνο πράγμα που πρέπει να λάβετε υπόψη κατά την αποστολή μηνυμάτων. Ας ρίξουμε μια ματιά στις μεθόδους send() της κλάσης Producer στο Java API:

Future < RecordMetadata > send(ProducerRecord < K, V > record);
Future < RecordMetadata > send(ProducerRecord < K, V > record, Callback callback);

Θα πρέπει αμέσως να σημειωθεί ότι και οι δύο μέθοδοι επιστρέφουν Future, κάτι που υποδεικνύει ότι η λειτουργία αποστολής δεν εκτελείται αμέσως. Το αποτέλεσμα είναι ότι ένα μήνυμα (ProducerRecord) γράφεται στο buffer αποστολής για κάθε ενεργό διαμέρισμα και αποστέλλεται στον μεσίτη ως νήμα φόντου στη βιβλιοθήκη πελάτη Kafka. Αν και αυτό κάνει τα πράγματα απίστευτα γρήγορα, σημαίνει ότι μια άπειρη εφαρμογή μπορεί να χάσει μηνύματα εάν διακοπεί η διαδικασία της.

Όπως πάντα, υπάρχει ένας τρόπος να γίνει η λειτουργία αποστολής πιο αξιόπιστη με κόστος απόδοσης. Το μέγεθος αυτού του buffer μπορεί να οριστεί στο 0 και το νήμα της εφαρμογής αποστολής θα αναγκαστεί να περιμένει μέχρι να ολοκληρωθεί η μεταφορά του μηνύματος στον μεσίτη, ως εξής:

RecordMetadata metadata = producer.send(record).get();

Περισσότερα για την ανάγνωση μηνυμάτων

Η ανάγνωση μηνυμάτων έχει πρόσθετες περιπλοκές για τις οποίες πρέπει να υποθέσουμε. Σε αντίθεση με το JMS API, το οποίο μπορεί να εκτελέσει ένα πρόγραμμα ακρόασης μηνυμάτων ως απόκριση σε ένα μήνυμα, το Καταναλωτής Κάφκα μόνο δημοσκοπήσεις. Ας ρίξουμε μια πιο προσεκτική ματιά στη μέθοδο ψηφοφορία()χρησιμοποιείται για το σκοπό αυτό:

ConsumerRecords < K, V > poll(long timeout);

Η τιμή επιστροφής της μεθόδου είναι μια δομή κοντέινερ που περιέχει πολλά αντικείμενα καταναλωτή από πιθανώς πολλά διαμερίσματα. καταναλωτή είναι το ίδιο αντικείμενο κατόχου για ένα ζεύγος κλειδιού-τιμής με συσχετισμένα μεταδεδομένα, όπως το διαμέρισμα από το οποίο προέρχεται.

Όπως συζητήθηκε στο Κεφάλαιο 2, πρέπει να έχουμε κατά νου τι συμβαίνει με τα μηνύματα μετά την επιτυχή ή ανεπιτυχή επεξεργασία τους, για παράδειγμα, εάν ο πελάτης δεν μπορεί να επεξεργαστεί το μήνυμα ή εάν αυτό ματαιωθεί. Στο JMS, αυτό έγινε μέσω μιας λειτουργίας επιβεβαίωσης. Ο μεσίτης είτε θα διαγράψει το επιτυχώς επεξεργασμένο μήνυμα είτε θα παραδώσει ξανά το ακατέργαστο ή ψεύτικο μήνυμα (υποθέτοντας ότι χρησιμοποιήθηκαν συναλλαγές).
Ο Κάφκα λειτουργεί πολύ διαφορετικά. Τα μηνύματα δεν διαγράφονται στον μεσίτη μετά τη διόρθωση και τι συμβαίνει σε περίπτωση αποτυχίας είναι ευθύνη του ίδιου του κώδικα διόρθωσης.

Όπως είπαμε, η ομάδα καταναλωτών σχετίζεται με τη μετατόπιση στο αρχείο καταγραφής. Η θέση καταγραφής που σχετίζεται με αυτή τη μετατόπιση αντιστοιχεί στο επόμενο μήνυμα που θα εκδοθεί ως απάντηση ψηφοφορία(). Το χρονικό σημείο που αυξάνεται αυτή η μετατόπιση είναι καθοριστικό για την ανάγνωση.

Επιστρέφοντας στο μοντέλο ανάγνωσης που συζητήθηκε προηγουμένως, η επεξεργασία του μηνύματος αποτελείται από τρία στάδια:

  1. Ανακτήστε ένα μήνυμα για ανάγνωση.
  2. Επεξεργαστείτε το μήνυμα.
  3. Επιβεβαίωση μηνύματος.

Ο καταναλωτής Kafka διαθέτει μια επιλογή διαμόρφωσης enable.auto.commit. Αυτή είναι μια προεπιλεγμένη ρύθμιση που χρησιμοποιείται συχνά, όπως συμβαίνει συνήθως με τις ρυθμίσεις που περιέχουν τη λέξη "auto".

Πριν από το Kafka 0.10, ένας πελάτης που χρησιμοποιεί αυτήν την επιλογή θα έστελνε τη μετατόπιση του τελευταίου μηνύματος που διαβάστηκε στην επόμενη κλήση ψηφοφορία() μετά την επεξεργασία. Αυτό σήμαινε ότι τυχόν μηνύματα που είχαν ήδη ληφθεί θα μπορούσαν να υποβληθούν σε επανεπεξεργασία εάν ο πελάτης τα είχε ήδη επεξεργαστεί αλλά καταστράφηκε απροσδόκητα πριν καλέσει ψηφοφορία(). Επειδή ο μεσίτης δεν κρατά καμία κατάσταση σχετικά με το πόσες φορές έχει διαβαστεί ένα μήνυμα, ο επόμενος καταναλωτής που θα ανακτήσει αυτό το μήνυμα δεν θα καταλάβει ότι συνέβη κάτι κακό. Αυτή η συμπεριφορά ήταν ψευδο-συναλλακτική. Η μετατόπιση δεσμεύτηκε μόνο εάν το μήνυμα είχε υποστεί επιτυχή επεξεργασία, αλλά εάν ο πελάτης ματαιωθεί, ο μεσίτης θα έστελνε ξανά το ίδιο μήνυμα σε άλλο πελάτη. Αυτή η συμπεριφορά ήταν σύμφωνη με την εγγύηση παράδοσης μηνυμάτων "τουλάχιστον μία φορά".

Στο Kafka 0.10, ο κωδικός πελάτη έχει αλλάξει έτσι ώστε η δέσμευση να ενεργοποιείται περιοδικά από τη βιβλιοθήκη πελάτη, όπως έχει ρυθμιστεί auto.commit.interval.ms. Αυτή η συμπεριφορά βρίσκεται κάπου μεταξύ των λειτουργιών JMS AUTO_ACKNOWLEDGE και DUPS_OK_ACKNOWLEDGE. Όταν χρησιμοποιείτε την αυτόματη δέσμευση, τα μηνύματα θα μπορούσαν να δεσμευτούν ανεξάρτητα από το αν όντως υποβλήθηκαν σε επεξεργασία - αυτό θα μπορούσε να συμβεί στην περίπτωση ενός αργού καταναλωτή. Εάν ένας καταναλωτής ματαιώσει, τα μηνύματα θα λαμβάνονταν από τον επόμενο καταναλωτή, ξεκινώντας από τη δεσμευμένη θέση, κάτι που θα μπορούσε να οδηγήσει σε χαμένο μήνυμα. Σε αυτή την περίπτωση, ο Κάφκα δεν έχασε τα μηνύματα, ο κώδικας ανάγνωσης απλώς δεν τα επεξεργάστηκε.

Αυτή η λειτουργία έχει την ίδια υπόσχεση όπως στην έκδοση 0.9: τα μηνύματα μπορούν να υποβληθούν σε επεξεργασία, αλλά εάν αποτύχει, η μετατόπιση ενδέχεται να μην δεσμευτεί, προκαλώντας ενδεχομένως τον διπλασιασμό της παράδοσης. Όσα περισσότερα μηνύματα λαμβάνετε κατά την εκτέλεση ψηφοφορία(), τόσο περισσότερο αυτό το πρόβλημα.

Όπως συζητήθηκε στην ενότητα «Ανάγνωση μηνυμάτων από μια ουρά» στη σελίδα 21, δεν υπάρχει μια εφάπαξ παράδοση ενός μηνύματος σε ένα σύστημα ανταλλαγής μηνυμάτων όταν λαμβάνονται υπόψη οι καταστάσεις αποτυχίας.

Στον Κάφκα, υπάρχουν δύο τρόποι για να πραγματοποιήσετε (δέσμευση) μια μετατόπιση (offset): αυτόματα και χειροκίνητα. Και στις δύο περιπτώσεις, τα μηνύματα μπορούν να υποβληθούν σε επεξεργασία πολλές φορές εάν το μήνυμα υποβλήθηκε σε επεξεργασία αλλά απέτυχε πριν από τη δέσμευση. Μπορείτε επίσης να επιλέξετε να μην επεξεργαστείτε καθόλου το μήνυμα εάν η δέσμευση συνέβη στο παρασκήνιο και ο κώδικάς σας ολοκληρώθηκε πριν μπορέσει να γίνει η επεξεργασία του (ίσως στο Kafka 0.9 και παλαιότερες).

Μπορείτε να ελέγξετε τη διαδικασία μη αυτόματης δέσμευσης μετατόπισης στο API καταναλωτή Kafka ορίζοντας την παράμετρο enable.auto.commit για ψευδή και ρητή κλήση μιας από τις ακόλουθες μεθόδους:

void commitSync();
void commitAsync();

Εάν θέλετε να επεξεργαστείτε το μήνυμα "τουλάχιστον μία φορά", πρέπει να πραγματοποιήσετε τη μετατόπιση χειροκίνητα με commitSync()εκτελώντας αυτήν την εντολή αμέσως μετά την επεξεργασία των μηνυμάτων.

Αυτές οι μέθοδοι δεν επιτρέπουν την επιβεβαίωση των μηνυμάτων πριν από την επεξεργασία τους, αλλά δεν κάνουν τίποτα για να εξαλείψουν πιθανές καθυστερήσεις επεξεργασίας ενώ δίνουν την εμφάνιση ότι είναι συναλλακτικά. Δεν υπάρχουν συναλλαγές στον Κάφκα. Ο πελάτης δεν έχει τη δυνατότητα να κάνει τα εξής:

  • Αυτόματη επαναφορά ενός πλαστού μηνύματος. Οι ίδιοι οι καταναλωτές πρέπει να χειρίζονται εξαιρέσεις που προκύπτουν από προβληματικά ωφέλιμα φορτία και διακοπές λειτουργίας, καθώς δεν μπορούν να βασίζονται στον μεσίτη για την εκ νέου παράδοση μηνυμάτων.
  • Στείλτε μηνύματα σε πολλά θέματα σε μία ατομική λειτουργία. Όπως θα δούμε σύντομα, ο έλεγχος διαφορετικών θεμάτων και κατατμήσεων μπορεί να βρίσκεται σε διαφορετικά μηχανήματα στο σύμπλεγμα Kafka που δεν συντονίζουν τις συναλλαγές όταν αποστέλλονται. Τη στιγμή που γράφεται αυτό το άρθρο, έχει γίνει κάποια εργασία για να γίνει αυτό δυνατό με το KIP-98.
  • Συσχετίστε την ανάγνωση ενός μηνύματος από ένα θέμα με την αποστολή ενός άλλου μηνύματος σε άλλο θέμα. Και πάλι, η αρχιτεκτονική του Κάφκα εξαρτάται από πολλές ανεξάρτητες μηχανές που λειτουργούν ως ένα λεωφορείο και δεν γίνεται καμία προσπάθεια να κρυφτεί αυτό. Για παράδειγμα, δεν υπάρχουν στοιχεία API που θα σας επέτρεπαν να συνδέσετε καταναλωτής и Παραγωγός σε μια συναλλαγή. Στο JMS, αυτό παρέχεται από το αντικείμενο Συνεδρίααπό τα οποία δημιουργούνται MessageProducers и ΜήνυμαΚαταναλωτές.

Εάν δεν μπορούμε να βασιστούμε στις συναλλαγές, πώς μπορούμε να παρέχουμε σημασιολογία πιο κοντά σε αυτά που παρέχουν τα παραδοσιακά συστήματα ανταλλαγής μηνυμάτων;

Εάν υπάρχει πιθανότητα να αυξηθεί η μετατόπιση του καταναλωτή πριν από την επεξεργασία του μηνύματος, όπως κατά τη διάρκεια μιας συντριβής καταναλωτή, τότε ο καταναλωτής δεν έχει τρόπο να γνωρίζει εάν η ομάδα καταναλωτών του έχασε το μήνυμα όταν της εκχωρήθηκε ένα διαμέρισμα. Επομένως, μια στρατηγική είναι να επαναφέρετε το offset στην προηγούμενη θέση. Το API καταναλωτή Kafka παρέχει τις ακόλουθες μεθόδους για αυτό:

void seek(TopicPartition partition, long offset);
void seekToBeginning(Collection < TopicPartition > partitions);

Μέθοδος ψάχνω() μπορεί να χρησιμοποιηθεί με τη μέθοδο
offsetsForTimes(Χάρτης timestampsToSearch) να επανατύλιξη σε μια κατάσταση σε κάποιο συγκεκριμένο σημείο του παρελθόντος.

Εμμέσως, η χρήση αυτής της προσέγγισης σημαίνει ότι είναι πολύ πιθανό ορισμένα μηνύματα που είχαν υποστεί επεξεργασία στο παρελθόν να διαβαστούν και να υποβληθούν σε επεξεργασία ξανά. Για να αποφευχθεί αυτό, μπορούμε να χρησιμοποιήσουμε την ανίκανη ανάγνωση, όπως περιγράφεται στο Κεφάλαιο 4, για να παρακολουθούμε τα μηνύματα που είδατε προηγουμένως και να εξαλείψουμε τα διπλότυπα.

Εναλλακτικά, ο κωδικός καταναλωτή σας μπορεί να παραμείνει απλός, εφόσον είναι αποδεκτή η απώλεια ή η αντιγραφή μηνύματος. Όταν εξετάζουμε περιπτώσεις χρήσης για τις οποίες χρησιμοποιείται συνήθως το Kafka, όπως ο χειρισμός συμβάντων καταγραφής, μετρήσεις, παρακολούθηση κλικ κ.λπ., κατανοούμε ότι η απώλεια μεμονωμένων μηνυμάτων είναι απίθανο να έχει σημαντικό αντίκτυπο στις γύρω εφαρμογές. Σε τέτοιες περιπτώσεις, οι προεπιλεγμένες τιμές είναι απολύτως αποδεκτές. Από την άλλη πλευρά, εάν η αίτησή σας χρειάζεται να στείλει πληρωμές, πρέπει να φροντίσετε προσεκτικά κάθε μεμονωμένο μήνυμα. Όλα καταλήγουν στο πλαίσιο.

Προσωπικές παρατηρήσεις δείχνουν ότι όσο αυξάνεται η ένταση των μηνυμάτων, η αξία κάθε μεμονωμένου μηνύματος μειώνεται. Τα μεγάλα μηνύματα τείνουν να είναι πολύτιμα όταν προβάλλονται σε συγκεντρωτική μορφή.

Μεγάλη διαθεσιμότητα

Η προσέγγιση του Kafka για την υψηλή διαθεσιμότητα είναι πολύ διαφορετική από την προσέγγιση του ActiveMQ. Το Kafka έχει σχεδιαστεί γύρω από συμπλέγματα κλιμάκωσης όπου όλα τα στιγμιότυπα μεσιτών λαμβάνουν και διανέμουν μηνύματα ταυτόχρονα.

Ένα σύμπλεγμα Kafka αποτελείται από πολλαπλές παρουσίες μεσίτη που εκτελούνται σε διαφορετικούς διακομιστές. Το Kafka σχεδιάστηκε για να λειτουργεί σε συνηθισμένο αυτόνομο υλικό, όπου κάθε κόμβος έχει τον δικό του αποκλειστικό χώρο αποθήκευσης. Η χρήση συνδεδεμένου χώρου αποθήκευσης δικτύου (SAN) δεν συνιστάται επειδή πολλοί κόμβοι υπολογιστών μπορούν να ανταγωνίζονται για το χρόνο.Ыδιαστήματα αποθήκευσης και δημιουργία διενέξεων.

Ο Κάφκα είναι πάντα ανοιχτό Σύστημα. Πολλοί μεγάλοι χρήστες του Kafka δεν κλείνουν ποτέ τα cluster τους και το λογισμικό ενημερώνεται πάντα με μια διαδοχική επανεκκίνηση. Αυτό επιτυγχάνεται με την εγγύηση συμβατότητας με την προηγούμενη έκδοση για μηνύματα και αλληλεπιδράσεις μεταξύ μεσιτών.

Μεσίτες που συνδέονται σε ένα σύμπλεγμα διακομιστών ZooKeeper, το οποίο λειτουργεί ως μητρώο δεδομένων διαμόρφωσης και χρησιμοποιείται για τον συντονισμό των ρόλων κάθε μεσίτη. Το ίδιο το ZooKeeper είναι ένα κατανεμημένο σύστημα που παρέχει υψηλή διαθεσιμότητα μέσω της αναπαραγωγής πληροφοριών με την καθιέρωση απαρτία.

Στη βασική περίπτωση, δημιουργείται ένα θέμα σε ένα σύμπλεγμα Kafka με τις ακόλουθες ιδιότητες:

  • Ο αριθμός των κατατμήσεων. Όπως αναφέρθηκε προηγουμένως, η ακριβής τιμή που χρησιμοποιείται εδώ εξαρτάται από το επιθυμητό επίπεδο παράλληλης ανάγνωσης.
  • Ο παράγοντας αναπαραγωγής (παράγοντας) καθορίζει πόσες παρουσίες μεσίτη στο σύμπλεγμα πρέπει να περιέχουν αρχεία καταγραφής για αυτό το διαμέρισμα.

Χρησιμοποιώντας το ZooKeepers για συντονισμό, ο Κάφκα επιχειρεί να διανείμει δίκαια νέα διαμερίσματα μεταξύ των μεσιτών στο σύμπλεγμα. Αυτό γίνεται από ένα μόνο στιγμιότυπο που λειτουργεί ως ελεγκτής.

Στο χρόνο εκτέλεσης για κάθε διαμέρισμα θέματος Ελεγκτής εκχωρήστε ρόλους σε έναν μεσίτη ηγέτης (αρχηγός, κύριος, παρουσιαστής) και οπαδούς (οπαδοί, δούλοι, υφιστάμενοι). Ο μεσίτης, ενεργώντας ως ηγέτης για αυτό το διαμέρισμα, είναι υπεύθυνος για τη λήψη όλων των μηνυμάτων που του αποστέλλονται από τους παραγωγούς και τη διανομή των μηνυμάτων στους καταναλωτές. Όταν τα μηνύματα αποστέλλονται σε ένα διαμέρισμα θέματος, αναπαράγονται σε όλους τους κόμβους μεσίτη που λειτουργούν ως ακόλουθοι για αυτό το διαμέρισμα. Κάθε κόμβος που περιέχει αρχεία καταγραφής για ένα διαμέρισμα καλείται πανομοιότυπο. Ένας μεσίτης μπορεί να λειτουργήσει ως ηγέτης για ορισμένα διαμερίσματα και ως ακόλουθος για άλλα.

Καλείται ένας ακόλουθος που περιέχει όλα τα μηνύματα που έχει ο αρχηγός συγχρονισμένο αντίγραφο (ένα αντίγραφο που βρίσκεται σε συγχρονισμένη κατάσταση, αντίγραφο σε συγχρονισμό). Εάν ένας μεσίτης που ενεργεί ως ηγέτης για ένα διαμέρισμα πέσει, οποιοσδήποτε μεσίτης είναι ενημερωμένος ή συγχρονισμένος για αυτό το διαμέρισμα μπορεί να αναλάβει τον ρόλο του ηγέτη. Είναι ένα απίστευτα βιώσιμο σχέδιο.

Μέρος της διαμόρφωσης παραγωγού είναι η παράμετρος λαβές, το οποίο καθορίζει πόσα αντίγραφα πρέπει να επιβεβαιώσουν (επιβεβαιώσουν) τη λήψη ενός μηνύματος προτού το νήμα της εφαρμογής συνεχίσει να στέλνει: 0, 1 ή όλα. Εάν έχει οριστεί σε όλοι, στη συνέχεια, όταν ληφθεί ένα μήνυμα, ο αρχηγός θα στείλει μια επιβεβαίωση πίσω στον παραγωγό μόλις λάβει επιβεβαιώσεις (επιβεβαιώσεις) της εγγραφής από πολλές ενδείξεις (συμπεριλαμβανομένου του ίδιου) που ορίζονται από τη ρύθμιση θέματος min.insync.replicas (προεπιλογή 1). Εάν το μήνυμα δεν μπορεί να αναπαραχθεί με επιτυχία, τότε ο παραγωγός θα δημιουργήσει μια εξαίρεση εφαρμογής (NotEnoughReplicas ή NotEnoughReplicasAfterAppend).

Μια τυπική διαμόρφωση δημιουργεί ένα θέμα με συντελεστή αναπαραγωγής 3 (1 leader, 2 followers ανά διαμέρισμα) και την παράμετρο min.insync.replicas έχει οριστεί σε 2. Σε αυτήν την περίπτωση, το σύμπλεγμα θα επιτρέψει σε έναν από τους μεσίτες που διαχειρίζονται το διαμέρισμα θέματος να μειωθεί χωρίς να επηρεαστούν οι εφαρμογές πελατών.

Αυτό μας φέρνει πίσω στην ήδη γνωστή αντιστάθμιση μεταξύ απόδοσης και αξιοπιστίας. Η αναπαραγωγή πραγματοποιείται εις βάρος του πρόσθετου χρόνου αναμονής για επιβεβαιώσεις (επιβεβαιώσεις) από τους ακόλουθους. Αν και, επειδή εκτελείται παράλληλα, η αναπαραγωγή σε τουλάχιστον τρεις κόμβους έχει την ίδια απόδοση με δύο (αγνοώντας την αύξηση της χρήσης εύρους ζώνης δικτύου).

Χρησιμοποιώντας αυτό το σχήμα αναπαραγωγής, ο Κάφκα αποφεύγει έξυπνα την ανάγκη φυσικής εγγραφής κάθε μηνύματος στο δίσκο με τη λειτουργία sync(). Κάθε μήνυμα που αποστέλλεται από τον παραγωγό θα γραφτεί στο αρχείο καταγραφής διαμερισμάτων, αλλά όπως συζητήθηκε στο Κεφάλαιο 2, η εγγραφή σε ένα αρχείο πραγματοποιείται αρχικά στο buffer του λειτουργικού συστήματος. Εάν αυτό το μήνυμα αναπαραχθεί σε μια άλλη περίπτωση του Κάφκα και βρίσκεται στη μνήμη του, η απώλεια του αρχηγού δεν σημαίνει ότι χάθηκε το ίδιο το μήνυμα - μπορεί να αναληφθεί από ένα συγχρονισμένο αντίγραφο.
Άρνηση εκτέλεσης της επέμβασης sync() σημαίνει ότι ο Κάφκα μπορεί να λάβει μηνύματα τόσο γρήγορα όσο μπορεί να τα γράψει στη μνήμη. Αντίθετα, όσο περισσότερο μπορείτε να αποφύγετε την έκπλυση της μνήμης στο δίσκο, τόσο το καλύτερο. Για το λόγο αυτό, δεν είναι ασυνήθιστο στους μεσίτες του Kafka να εκχωρούνται 64 GB ή περισσότερα μνήμης. Αυτή η χρήση μνήμης σημαίνει ότι μια μεμονωμένη παρουσία του Kafka μπορεί εύκολα να εκτελεστεί με ταχύτητες πολλές χιλιάδες φορές μεγαλύτερες από έναν παραδοσιακό μεσίτη μηνυμάτων.

Το Kafka μπορεί επίσης να ρυθμιστεί για να εφαρμόσει τη λειτουργία sync() σε πακέτα μηνυμάτων. Δεδομένου ότι τα πάντα στο Kafka είναι προσανατολισμένα στο πακέτο, στην πραγματικότητα λειτουργεί αρκετά καλά για πολλές περιπτώσεις χρήσης και είναι ένα χρήσιμο εργαλείο για χρήστες που απαιτούν πολύ ισχυρές εγγυήσεις. Μεγάλο μέρος της καθαρής απόδοσης του Κάφκα προέρχεται από τα μηνύματα που αποστέλλονται στον μεσίτη ως πακέτα και ότι αυτά τα μηνύματα διαβάζονται από τον μεσίτη σε διαδοχικά μπλοκ χρησιμοποιώντας μηδενικό αντίγραφο λειτουργίες (λειτουργίες κατά τις οποίες δεν εκτελείται η εργασία αντιγραφής δεδομένων από μια περιοχή μνήμης σε άλλη). Το τελευταίο είναι ένα μεγάλο κέρδος απόδοσης και πόρων και είναι δυνατό μόνο μέσω της χρήσης μιας υποκείμενης δομής δεδομένων καταγραφής που καθορίζει το σχήμα διαμερισμάτων.

Πολύ καλύτερη απόδοση είναι δυνατή σε ένα σύμπλεγμα Kafka από ό,τι με έναν μεσολαβητή Kafka, επειδή οι κατατμήσεις θεμάτων μπορούν να κλιμακωθούν σε πολλά ξεχωριστά μηχανήματα.

Αποτελέσματα της

Σε αυτό το κεφάλαιο, εξετάσαμε τον τρόπο με τον οποίο η αρχιτεκτονική Kafka επαναπροσδιορίζει τη σχέση μεταξύ πελατών και μεσιτών για να παρέχει έναν απίστευτα ισχυρό αγωγό ανταλλαγής μηνυμάτων, με απόδοση πολλές φορές μεγαλύτερη από αυτή ενός συμβατικού μεσίτη μηνυμάτων. Συζητήσαμε τη λειτουργικότητα που χρησιμοποιεί για να το πετύχει αυτό και εξετάσαμε εν συντομία την αρχιτεκτονική των εφαρμογών που παρέχουν αυτήν τη λειτουργικότητα. Στο επόμενο κεφάλαιο, θα εξετάσουμε κοινά προβλήματα που πρέπει να επιλύσουν οι εφαρμογές που βασίζονται σε μηνύματα και θα συζητήσουμε στρατηγικές για την αντιμετώπισή τους. Θα ολοκληρώσουμε το κεφάλαιο περιγράφοντας πώς να μιλάμε για τις τεχνολογίες ανταλλαγής μηνυμάτων γενικά, ώστε να μπορείτε να αξιολογήσετε την καταλληλότητά τους για τις περιπτώσεις χρήσης σας.

Προηγούμενο μεταφρασμένο μέρος: Κατανόηση των μεσιτών μηνυμάτων. Μαθαίνοντας τους μηχανισμούς των μηνυμάτων με το ActiveMQ και τον Kafka. Κεφάλαιο 1

Η μετάφραση έγινε: tele.gg/middle_java

Για να συνεχιστεί ...

Μόνο εγγεγραμμένοι χρήστες μπορούν να συμμετάσχουν στην έρευνα. Συνδεθείτε, Σας παρακαλούμε.

Χρησιμοποιείται ο Κάφκα στον οργανισμό σας;

  • Ναί

  • Όχι

  • Παλαιότερα χρησιμοποιήθηκε, τώρα όχι

  • Σχεδιάζουμε να χρησιμοποιήσουμε

Ψήφισαν 38 χρήστες. 8 χρήστες απείχαν.

Πηγή: www.habr.com

Προσθέστε ένα σχόλιο