Όχι μόνο επεξεργασία: Πώς φτιάξαμε μια κατανεμημένη βάση δεδομένων από το Kafka Streams και τι προέκυψε από αυτήν

Γεια σου Χαμπρ!

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

Όχι μόνο επεξεργασία: Πώς φτιάξαμε μια κατανεμημένη βάση δεδομένων από το Kafka Streams και τι προέκυψε από αυτήν

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

Βιβλιοθήκη Apache Ρεύματα Κάφκα χρησιμοποιείται παγκοσμίως σε επιχειρήσεις για την επεξεργασία κατανεμημένων ροών πάνω από τον Apache Kafka. Μία από τις υποτιμημένες πτυχές αυτού του πλαισίου είναι ότι σας επιτρέπει να αποθηκεύετε τοπική κατάσταση που παράγεται με βάση την επεξεργασία νημάτων.

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

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

Γιατί πιστεύαμε ότι ήταν καιρός να αλλάξουμε τον τρόπο που εργαζόμαστε με το κοινό κράτος

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

Όχι μόνο επεξεργασία: Πώς φτιάξαμε μια κατανεμημένη βάση δεδομένων από το Kafka Streams και τι προέκυψε από αυτήν

Εικόνα 1: Ένα τυπικό σενάριο διαίρεσης κατάστασης που παρατηρήθηκε πριν από τη μετάβαση σε
Kafka και Kafka Streams: οι πράκτορες επικοινωνούν τις απόψεις τους μέσω API, η ενημερωμένη κατάσταση υπολογίζεται μέσω μιας κεντρικής βάσης δεδομένων

Γνωρίστε το Kafka Streams, διευκολύνοντας τη δημιουργία κοινών κρατικών μικροϋπηρεσιών

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

Κάθε μια από τις κρατικές μικροϋπηρεσίες που δημιουργήσαμε χτίστηκε πάνω από μια παρουσία του Kafka Streams με μια αρκετά απλή τοπολογία. Αποτελούνταν από 1) μια πηγή 2) έναν επεξεργαστή με μόνιμο χώρο αποθήκευσης κλειδιών-τιμών 3) έναν νεροχύτη:

Όχι μόνο επεξεργασία: Πώς φτιάξαμε μια κατανεμημένη βάση δεδομένων από το Kafka Streams και τι προέκυψε από αυτήν

Εικόνα 2: Η προεπιλεγμένη τοπολογία των παρουσιών ροής μας για κρατικές μικροϋπηρεσίες. Σημειώστε ότι υπάρχει επίσης ένα αποθετήριο εδώ που περιέχει μεταδεδομένα προγραμματισμού.

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

Όχι μόνο επεξεργασία: Πώς φτιάξαμε μια κατανεμημένη βάση δεδομένων από το Kafka Streams και τι προέκυψε από αυτήν

Εικόνα 3: Νέο παράδειγμα ροής εργασιών για ένα σενάριο με κοινόχρηστες μικροϋπηρεσίες: 1) ο πράκτορας δημιουργεί ένα μήνυμα που φτάνει στο θέμα της πηγής Kafka. 2) μια μικρουπηρεσία με κοινή κατάσταση (χρησιμοποιώντας το Kafka Streams) την επεξεργάζεται και εγγράφει την υπολογιζόμενη κατάσταση στο τελικό θέμα Kafka. μετά την οποία 3) οι καταναλωτές αποδέχονται τη νέα κατάσταση

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

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

Επιλογή #1: Χρησιμοποιήστε ένα χώρο αποθήκευσης κλειδιού-τιμής για υπολογισμούς

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

Όχι μόνο επεξεργασία: Πώς φτιάξαμε μια κατανεμημένη βάση δεδομένων από το Kafka Streams και τι προέκυψε από αυτήν

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

Επιλογή #2: Δημιουργία CRUD API πάνω από το Kafka Streams

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

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

Όχι μόνο επεξεργασία: Πώς φτιάξαμε μια κατανεμημένη βάση δεδομένων από το Kafka Streams και τι προέκυψε από αυτήν

Εικόνα 5: Χρήση του ενσωματωμένου χώρου αποθήκευσης κλειδιού-τιμής για την απόκτηση της προυπολογισμένης κατάστασης ενός αντικειμένου

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

Όχι μόνο επεξεργασία: Πώς φτιάξαμε μια κατανεμημένη βάση δεδομένων από το Kafka Streams και τι προέκυψε από αυτήν

Εικόνα 6: Μπορείτε να ορίσετε την κατάσταση ενός αντικειμένου χρησιμοποιώντας τον παραγωγό Kafka

Μικρή επιπλοκή: Ο Κάφκα έχει πολλά χωρίσματα

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

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

Μεταβαίνοντας από μια ενιαία microservice με κοινόχρηστη κατάσταση σε ένα σύμπλεγμα μικροϋπηρεσιών, καθίσταται λιγότερο ασήμαντη η εφαρμογή του Get State API. Στη νέα κατάσταση, η κατάσταση αποθήκευσης κάθε microservice περιέχει μόνο μέρος της συνολικής εικόνας (τα αντικείμενα των οποίων τα κλειδιά αντιστοιχίστηκαν σε ένα συγκεκριμένο διαμέρισμα). Έπρεπε να προσδιορίσουμε ποια παρουσία περιείχε την κατάσταση του αντικειμένου που χρειαζόμασταν και το κάναμε με βάση τα μεταδεδομένα του νήματος, όπως φαίνεται παρακάτω:

Όχι μόνο επεξεργασία: Πώς φτιάξαμε μια κατανεμημένη βάση δεδομένων από το Kafka Streams και τι προέκυψε από αυτήν

Εικόνα 7: Χρησιμοποιώντας μεταδεδομένα ροής, προσδιορίζουμε από ποια στιγμιότυπα θα ρωτήσουμε την κατάσταση του επιθυμητού αντικειμένου. Μια παρόμοια προσέγγιση χρησιμοποιήθηκε με το GET ALL API

Βασικά ευρήματα

Τα κρατικά καταστήματα στο Kafka Streams μπορούν να χρησιμεύσουν ως de facto κατανεμημένη βάση δεδομένων,

  • αναπαράγεται συνεχώς στον Κάφκα
  • Ένα CRUD API μπορεί εύκολα να κατασκευαστεί πάνω από ένα τέτοιο σύστημα
  • Ο χειρισμός πολλαπλών κατατμήσεων είναι λίγο πιο περίπλοκος
  • Είναι επίσης δυνατή η προσθήκη ενός ή περισσότερων καταστάσεων αποθήκευσης στην τοπολογία ροής για την αποθήκευση βοηθητικών δεδομένων. Αυτή η επιλογή μπορεί να χρησιμοποιηθεί για:
  • Μακροπρόθεσμη αποθήκευση δεδομένων που απαιτούνται για υπολογισμούς κατά την επεξεργασία ροής
  • Μακροπρόθεσμη αποθήκευση δεδομένων που μπορεί να είναι χρήσιμα την επόμενη φορά που παρέχεται η παρουσία ροής
  • πολύ περισσότερο...

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

Πηγή: www.habr.com

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