Πρόβλημα διπλής εγγραφής
Η οικοδόμηση ενός αξιόπιστου, εξαιρετικά διαθέσιμου, κλιμακούμενου κατανεμημένου συστήματος απαιτεί την τήρηση συγκεκριμένων τεχνικών, αρχών και προτύπων. Ο σχεδιασμός τέτοιων συστημάτων περιλαμβάνει την αντιμετώπιση μυριάδων προκλήσεων. Μεταξύ των πιο διαδεδομένων και θεμελιωδών ζητημάτων είναι το πρόβλημα διπλής εγγραφής .
Το «πρόβλημα διπλής εγγραφής» είναι μια πρόκληση που προκύπτει στα κατανεμημένα συστήματα, κυρίως όταν έχουμε να κάνουμε με πολλαπλές πηγές δεδομένων ή βάσεις δεδομένων που πρέπει να διατηρούνται σε συγχρονισμό. Αναφέρεται στη δυσκολία διασφάλισης ότι οι αλλαγές δεδομένων εγγράφονται με συνέπεια σε διάφορες αποθήκες δεδομένων, όπως βάσεις δεδομένων ή κρυφές μνήμες, χωρίς να εισάγονται ζητήματα όπως ασυνέπειες δεδομένων, διενέξεις ή συμφόρηση απόδοσης.
Η αρχιτεκτονική microservices και η βάση δεδομένων προτύπων ανά υπηρεσία σας αποφέρουν πολλά πλεονεκτήματα, όπως ανεξάρτητη ανάπτυξη και κλιμάκωση, μεμονωμένες αποτυχίες και πιθανή ώθηση της ταχύτητας ανάπτυξης. Ωστόσο, οι λειτουργίες απαιτούν αλλαγές μεταξύ πολλών μικροϋπηρεσιών, αναγκάζοντάς σας να σκεφτείτε μια αξιόπιστη λύση για την αντιμετώπιση αυτού του προβλήματος.
Σχεδόν πραγματικό παράδειγμα
Ας εξετάσουμε ένα σενάριο στο οποίο ο τομέας μας περιλαμβάνει την αποδοχή αιτήσεων δανείου, την αξιολόγησή τους και, στη συνέχεια, την αποστολή ειδοποιήσεων ειδοποιήσεων στους πελάτες.
Στο πνεύμα της αρχής της ενιαίας ευθύνης, του νόμου του Conway και της προσέγγισης σχεδίασης βάσει τομέα, μετά από αρκετές συνεδρίες καταιγισμού συμβάντων, ολόκληρος ο τομέας χωρίστηκε σε τρεις υποτομείς με καθορισμένα οριοθετημένα περιβάλλοντα με σαφή όρια, μοντέλα τομέα και πανταχού παρούσα γλώσσα.
Το πρώτο έχει ως αποστολή την ενσωμάτωση και τη σύνταξη νέων αιτήσεων δανείου. Το δεύτερο σύστημα αξιολογεί αυτές τις εφαρμογές και λαμβάνει αποφάσεις με βάση τα δεδομένα που παρέχονται. Αυτή η διαδικασία αξιολόγησης, συμπεριλαμβανομένων των ελέγχων KYC/KYB, καταπολέμησης απάτης και πιστωτικού κινδύνου, μπορεί να είναι χρονοβόρα, καθιστώντας απαραίτητη τη δυνατότητα ταυτόχρονης διαχείρισης χιλιάδων αιτήσεων. Κατά συνέπεια, αυτή η λειτουργία έχει ανατεθεί σε μια αποκλειστική μικρουπηρεσία με τη δική της βάση δεδομένων, επιτρέποντας την ανεξάρτητη κλιμάκωση.
Επιπλέον, αυτά τα υποσυστήματα διαχειρίζονται δύο διαφορετικές ομάδες, η καθεμία με τους δικούς της κύκλους κυκλοφορίας, συμφωνίες επιπέδου υπηρεσιών (SLA) και απαιτήσεις επεκτασιμότητας.
Τέλος , υπάρχει μια εξειδικευμένη υπηρεσία ειδοποιήσεων για την αποστολή ειδοποιήσεων στους πελάτες.
Ακολουθεί μια εκλεπτυσμένη περιγραφή της περίπτωσης κύριας χρήσης του συστήματος:
- Ένας πελάτης υποβάλλει αίτηση δανείου.
- Η Υπηρεσία Αίτησης Δανείου καταγράφει τη νέα αίτηση με κατάσταση «Εκκρεμεί» και ξεκινά τη διαδικασία αξιολόγησης προωθώντας την αίτηση στην Υπηρεσία Αξιολόγησης.
- Η Υπηρεσία Αξιολόγησης αξιολογεί την εισερχόμενη αίτηση δανείου και στη συνέχεια ενημερώνει την Υπηρεσία Αιτήσεων Δανείου για την απόφαση.
- Μετά τη λήψη της απόφασης, η Υπηρεσία Αίτησης Δανείου ενημερώνει ανάλογα την κατάσταση της αίτησης δανείου και ενεργοποιεί την Υπηρεσία Ειδοποιήσεων για να ενημερώσει τον πελάτη για το αποτέλεσμα.
- Η Υπηρεσία Ειδοποιήσεων επεξεργάζεται αυτό το αίτημα και αποστέλλει ειδοποιήσεις στον πελάτη μέσω email, SMS ή άλλων προτιμώμενων μεθόδων επικοινωνίας, σύμφωνα με τις ρυθμίσεις του πελάτη.
Είναι ένα αρκετά απλό και πρωτόγονο σύστημα με την πρώτη ματιά, αλλά ας δούμε πώς η υπηρεσία αίτησης δανείου επεξεργάζεται την εντολή υποβολής αίτησης δανείου.
Μπορούμε να εξετάσουμε δύο προσεγγίσεις για αλληλεπιδράσεις υπηρεσιών:
First-Local-Commit-Then-Publish: Σε αυτήν την προσέγγιση, η υπηρεσία ενημερώνει την τοπική της βάση δεδομένων (commits) και στη συνέχεια δημοσιεύει ένα συμβάν ή ένα μήνυμα σε άλλες υπηρεσίες.
First-Publish-Then-Local-Commit: Αντίθετα, αυτή η μέθοδος περιλαμβάνει τη δημοσίευση ενός συμβάντος ή ενός μηνύματος πριν από την πραγματοποίηση των αλλαγών στην τοπική βάση δεδομένων.
Και οι δύο μέθοδοι έχουν τα μειονεκτήματά τους και είναι μόνο εν μέρει ασφαλείς έναντι αστοχίας για επικοινωνία σε κατανεμημένα συστήματα.
Αυτό είναι ένα διάγραμμα ακολουθίας εφαρμογής της πρώτης προσέγγισης.
Σε αυτό το σενάριο, η Υπηρεσία Αίτησης Δανείου χρησιμοποιεί την προσέγγιση First-Local-Commit-Then-Publish , όπου πρώτα δεσμεύει μια συναλλαγή και στη συνέχεια επιχειρεί να στείλει μια ειδοποίηση σε άλλο σύστημα. Ωστόσο, αυτή η διαδικασία ενδέχεται να αποτύχει εάν, για παράδειγμα, υπάρχουν ζητήματα δικτύου, η Υπηρεσία Αξιολόγησης δεν είναι διαθέσιμη ή η Υπηρεσία Αίτησης Δανείου αντιμετωπίσει σφάλμα εκτός μνήμης (OOM) και διακοπεί. Σε τέτοιες περιπτώσεις, το μήνυμα θα χαθεί, αφήνοντας την Αξιολόγηση χωρίς ειδοποίηση για τη νέα αίτηση δανείου, εκτός εάν εφαρμοστούν πρόσθετα μέτρα.
Και το δεύτερο.
Στο σενάριο First-Publish-Then-Local-Commit , η Υπηρεσία Αίτησης Δανείου αντιμετωπίζει σημαντικότερους κινδύνους. Ενδέχεται να ενημερώσει την Υπηρεσία Αξιολόγησης για μια νέα εφαρμογή, αλλά να αποτύχει να αποθηκεύσει αυτήν την ενημέρωση τοπικά λόγω προβλημάτων όπως ζητήματα βάσης δεδομένων, σφάλματα μνήμης ή σφάλματα κώδικα. Αυτή η προσέγγιση μπορεί να οδηγήσει σε σημαντικές ασυνέπειες στα δεδομένα, που θα μπορούσαν να προκαλέσουν σοβαρά προβλήματα, ανάλογα με τον τρόπο με τον οποίο η Υπηρεσία Αναθεώρησης Δανείου χειρίζεται τις εισερχόμενες αιτήσεις.
Επομένως, πρέπει να εντοπίσουμε μια λύση που να προσφέρει έναν ισχυρό μηχανισμό για τη δημοσίευση συμβάντων σε εξωτερικούς καταναλωτές. Ωστόσο, πριν εμβαθύνουμε σε πιθανές λύσεις, θα πρέπει πρώτα να διευκρινίσουμε τους τύπους εγγυήσεων παράδοσης μηνυμάτων που μπορούν να επιτευχθούν σε κατανεμημένα συστήματα.
Εγγυήσεις παράδοσης μηνυμάτων
Υπάρχουν τέσσερις τύποι εγγυήσεων που θα μπορούσαμε να επιτύχουμε.
Καμία εγγύηση
Δεν υπάρχει καμία εγγύηση ότι το μήνυμα θα παραδοθεί στον προορισμό. Η προσέγγιση First-Local-Commit-Then-Publish αφορά ακριβώς αυτό. Οι καταναλωτές ενδέχεται να λαμβάνουν μηνύματα μία φορά, πολλές φορές ή και ποτέ.Το πολύ μια φορά παράδοση
Το πολύ μία φορά παράδοση σημαίνει ότι το μήνυμα θα παραδοθεί στον προορισμό το πολύ 1 φορά. Η προσέγγιση First-Local-Commit-Then-Publish μπορεί να εφαρμοστεί με αυτόν τον τρόπο και με την πολιτική επανάληψης προσπαθειών με τιμή ένα.Τουλάχιστον μία φορά παράδοση\Οι καταναλωτές θα λάβουν και θα επεξεργαστούν κάθε μήνυμα, αλλά ενδέχεται να λάβουν το ίδιο μήνυμα περισσότερες από μία φορές.
Ακριβώς μία φορά παράδοση\Ακριβώς μία φορά παράδοση σημαίνει ότι ο καταναλωτής θα λάβει το μήνυμα αποτελεσματικά μία φορά.
Τεχνικά, είναι δυνατό να επιτευχθούν με τον Κάφκα συναλλαγές και συγκεκριμένη ανίκανη εφαρμογή παραγωγού και καταναλωτή.
Στις περισσότερες περιπτώσεις, οι εγγυήσεις παράδοσης «τουλάχιστον μία φορά» αντιμετωπίζουν πολλά ζητήματα διασφαλίζοντας ότι τα μηνύματα παραδίδονται τουλάχιστον μία φορά, αλλά οι καταναλωτές πρέπει να είναι ανίκανοι. Ωστόσο, λαμβάνοντας υπόψη τις αναπόφευκτες βλάβες του δικτύου, όλη η λογική των καταναλωτών πρέπει να είναι ανίκανη για την αποφυγή επεξεργασίας διπλών μηνυμάτων, ανεξάρτητα από τις εγγυήσεις του παραγωγού. Επομένως, αυτή η απαίτηση δεν είναι τόσο μειονέκτημα όσο αντικατοπτρίζει την πραγματικότητα.
Λύσεις
Υπάρχουν πολλές λύσεις σε αυτό το πρόβλημα, οι οποίες έχουν τα πλεονεκτήματα και τα μειονεκτήματά τους.
Δέσμευση δύο φάσεων
Σύμφωνα με τη Wikipedia, το Two-Phase Commit (2PC) είναι ένα πρωτόκολλο κατανεμημένων συναλλαγών που χρησιμοποιείται στην επιστήμη των υπολογιστών και στα συστήματα διαχείρισης βάσεων δεδομένων για να διασφαλιστεί η συνέπεια και η αξιοπιστία των κατανεμημένων συναλλαγών. Έχει σχεδιαστεί για περιπτώσεις όπου πολλοί πόροι (π.χ. βάσεις δεδομένων) πρέπει να συμμετέχουν σε μία μόνο συναλλαγή και διασφαλίζει ότι είτε όλοι δεσμεύουν τη συναλλαγή είτε τη ματαιώνουν όλοι, διατηρώντας έτσι τη συνέπεια των δεδομένων. Ακούγεται ακριβώς αυτό που χρειαζόμαστε, αλλά το Two-Phase Commit έχει αρκετά μειονεκτήματα:
- Εάν ένας συμμετέχων πόρος δεν ανταποκρίνεται ή παρουσιάσει αποτυχία, ολόκληρη η διαδικασία μπορεί να αποκλειστεί μέχρι να επιλυθεί το πρόβλημα. Αυτό μπορεί να οδηγήσει σε πιθανά προβλήματα απόδοσης και διαθεσιμότητας.
- Η δέσμευση δύο φάσεων δεν παρέχει ενσωματωμένους μηχανισμούς ανοχής σφαλμάτων. Βασίζεται σε εξωτερικούς μηχανισμούς ή χειροκίνητη παρέμβαση για την αντιμετώπιση αστοχιών.
- Δεν υποστηρίζουν όλες οι σύγχρονες βάσεις δεδομένων το Two-Phase Commit.
Κοινή βάση δεδομένων
Η πιο προφανής λύση για την αρχιτεκτονική των μικροϋπηρεσιών είναι η εφαρμογή ενός μοτίβου (ή ακόμη και μερικές φορές αντι-μοτίβου) — μια κοινή βάση δεδομένων. Αυτή η προσέγγιση είναι πολύ διαισθητική εάν χρειάζεστε συνέπεια συναλλαγών σε πολλούς πίνακες σε διαφορετικές βάσεις δεδομένων, απλώς χρησιμοποιήστε μια κοινόχρηστη βάση δεδομένων για αυτές τις μικροϋπηρεσίες.
Τα μειονεκτήματα αυτής της προσέγγισης περιλαμβάνουν την εισαγωγή ενός μόνο σημείου αστοχίας, την αναστολή της κλίμακας ανεξάρτητης βάσης δεδομένων και τον περιορισμό της δυνατότητας χρήσης διαφορετικών λύσεων βάσεων δεδομένων που ταιριάζουν καλύτερα για συγκεκριμένες απαιτήσεις και περιπτώσεις χρήσης. Επιπλέον, θα ήταν απαραίτητες τροποποιήσεις στις βάσεις κωδικών μικροϋπηρεσιών για την υποστήριξη μιας τέτοιας μορφής κατανεμημένης συναλλαγής.
Εξερχόμενα συναλλαγών
Τα « εξερχόμενα συναλλαγών » είναι ένα μοτίβο σχεδιασμού που χρησιμοποιείται σε κατανεμημένα συστήματα για τη διασφάλιση αξιόπιστης μετάδοσης μηνυμάτων, ακόμη και σε περίπτωση αναξιόπιστων συστημάτων ανταλλαγής μηνυμάτων. Περιλαμβάνει την αποθήκευση συμβάντων σε έναν καθορισμένο πίνακα "ΕξερχόμεναΕvents" εντός της ίδιας συναλλαγής με την ίδια τη λειτουργία. Αυτή η προσέγγιση ευθυγραμμίζεται καλά με τις ιδιότητες ACID των σχεσιακών βάσεων δεδομένων. Αντίθετα, πολλές βάσεις δεδομένων No-SQL δεν υποστηρίζουν πλήρως τις ιδιότητες ACID, επιλέγοντας αντ' αυτού τις αρχές του θεωρήματος CAP και της φιλοσοφίας BASE, που δίνουν προτεραιότητα στη διαθεσιμότητα και την τελική συνέπεια έναντι της αυστηρής συνέπειας.
Τα εξερχόμενα συναλλαγών παρέχει τουλάχιστον μία φορά εγγύηση και μπορεί να εφαρμοστεί με διάφορες προσεγγίσεις:
Καταγραφή ημερολογίου συναλλαγών
Εκδότης δημοσκοπήσεων
Η προσέγγιση τελικής καταγραφής συναλλαγών συνεπάγεται τη χρήση λύσεων για συγκεκριμένες βάσεις δεδομένων, όπως το CDC (Change Data Capture). Τα κύρια μειονεκτήματα αυτής της προσέγγισης είναι:
Ειδικές λύσεις βάσης δεδομένων
Αυξημένη καθυστέρηση λόγω των ιδιαιτεροτήτων των υλοποιήσεων CDC
Μια άλλη μέθοδος είναι το Polling Publisher , που διευκολύνει την εκφόρτωση των εξερχόμενων ψηφοφοριών στον πίνακα εξερχόμενων. Το κύριο μειονέκτημα αυτής της προσέγγισης είναι η πιθανότητα αυξημένου φόρτου βάσης δεδομένων, που μπορεί να οδηγήσει σε υψηλότερο κόστος. Επιπλέον, δεν υποστηρίζουν όλες οι βάσεις δεδομένων No-SQL αποτελεσματική αναζήτηση για συγκεκριμένα τμήματα εγγράφων. Επομένως, η εξαγωγή ολόκληρων εγγράφων μπορεί να οδηγήσει σε υποβάθμιση της απόδοσης.
Εδώ είναι ένα μικρό διάγραμμα ακολουθίας που εξηγεί πώς λειτουργεί.
Ακούστε τον εαυτό σας
Η κύρια πρόκληση με το μοτίβο των εξερχόμενων συναλλαγών έγκειται στην εξάρτησή του από τις ιδιότητες ACID της βάσης δεδομένων. Μπορεί να είναι απλό σε τυπικές βάσεις δεδομένων OLTP, αλλά δημιουργεί προκλήσεις στη σφαίρα NoSQL. Για να αντιμετωπιστεί αυτό, μια πιθανή λύση είναι η αξιοποίηση του αρχείου καταγραφής προσαρτήσεων (για παράδειγμα, ο Kafka) αμέσως από την έναρξη της επεξεργασίας αιτημάτων.
Αντί να επεξεργαστούμε απευθείας την εντολή «υποβολή αίτησης δανείου», τη στέλνουμε αμέσως σε ένα εσωτερικό θέμα του Κάφκα και στη συνέχεια επιστρέφουμε ένα «αποδεκτό» αποτέλεσμα στον πελάτη. Ωστόσο, καθώς είναι πολύ πιθανό η εντολή να χρειάζεται ακόμη επεξεργασία, δεν μπορούμε να ενημερώσουμε αμέσως τον πελάτη για το αποτέλεσμα. Για να διαχειριστούμε αυτήν την ενδεχόμενη συνέπεια, μπορούμε να χρησιμοποιήσουμε τεχνικές όπως μακρά δημοσκόπηση, δημοσκόπηση που ξεκινά από τον πελάτη, αισιόδοξες ενημερώσεις διεπαφής χρήστη ή χρήση WebSockets ή συμβάντων που απεστάλησαν από διακομιστή για ειδοποιήσεις. Ωστόσο, αυτό είναι ένα ξεχωριστό θέμα συνολικά, οπότε ας επιστρέψουμε στο αρχικό μας θέμα.
Στείλαμε το μήνυμα για ένα εσωτερικό θέμα του Κάφκα. Στη συνέχεια, η Υπηρεσία Αίτησης Δανείου καταναλώνει αυτό το μήνυμα - την ίδια εντολή που έλαβε από τον πελάτη - και ξεκινά την επεξεργασία. Πρώτον, εκτελεί κάποια επιχειρηματική λογική. μόνο αφού εκτελεστεί επιτυχώς αυτή η λογική και διατηρηθούν τα αποτελέσματα, δημοσιεύει νέα μηνύματα σε ένα δημόσιο θέμα Κάφκα.
Ας ρίξουμε μια ματιά σε λίγο ψευδο-κώδικα.
public async Task HandleAsync(SubmitLoanApplicationCommand command, ...) { //First, process business logic var loanApplication = await _loanApplicationService.HandleCommandAsync(command, ...); //Then, send new events to public Kafka topic producer.Send(new LoanApplicationSubmittedEvent(loanApplication.Id)); //Then, commit offset consumer.Commit(); }
Τι γίνεται αν αποτύχει η επεξεργασία της επιχειρηματικής λογικής; Μην ανησυχείτε, καθώς η μετατόπιση δεν έχει ακόμη πραγματοποιηθεί, το μήνυμα θα επαναληφθεί.
Τι γίνεται αν η αποστολή νέων γεγονότων στον Κάφκα αποτύχει; Μην ανησυχείτε, καθώς η επιχειρηματική λογική είναι ανίκανη, δεν θα δημιουργήσει διπλή αίτηση δανείου. Αντίθετα, θα προσπαθήσει να στείλει ξανά μηνύματα στο δημόσιο θέμα του Κάφκα.
Τι γίνεται αν σταλούν μηνύματα στον Κάφκα, αλλά η δέσμευση offset αποτύχει; Μην ανησυχείτε, καθώς η επιχειρηματική λογική είναι ανίκανη, δεν θα δημιουργήσει μια διπλή αίτηση δανείου. Αντίθετα, θα στείλει ξανά μηνύματα στο δημόσιο θέμα του Κάφκα και ελπίζει ότι αυτή τη φορά η δέσμευση offset θα πετύχει.
Τα κύρια μειονεκτήματα αυτής της προσέγγισης περιλαμβάνουν την πρόσθετη πολυπλοκότητα που σχετίζεται με ένα νέο στυλ προγραμματισμού, την τελική συνέπεια (καθώς ο πελάτης δεν θα γνωρίζει αμέσως το αποτέλεσμα) και την απαίτηση να είναι ανίκανη όλη η επιχειρηματική λογική.
Πηγή εκδήλωσης
Τι είναι η προέλευση συμβάντων και πώς θα μπορούσε να εφαρμοστεί εδώ; Η προέλευση συμβάντων είναι ένα αρχιτεκτονικό πρότυπο λογισμικού που χρησιμοποιείται για τη μοντελοποίηση της κατάστασης ενός συστήματος καταγράφοντας όλες τις αλλαγές στα δεδομένα του ως μια σειρά από αμετάβλητα συμβάντα. Αυτά τα γεγονότα αντιπροσωπεύουν γεγονότα ή μεταβάσεις καταστάσεων και χρησιμεύουν ως η μοναδική πηγή αλήθειας για την τρέχουσα κατάσταση του συστήματος. Έτσι, τεχνικά, εφαρμόζοντας ένα σύστημα προέλευσης συμβάντων, έχουμε ήδη όλα τα συμβάντα στο EventStore και αυτό το EventStore μπορεί να χρησιμοποιηθεί από τους καταναλωτές ως μια ενιαία πηγή αλήθειας για το τι συνέβη. Δεν υπάρχει ανάγκη για μια συγκεκριμένη λύση βάσης δεδομένων για την παρακολούθηση όλων των αλλαγών ή ανησυχιών σχετικά με την παραγγελία, το μόνο πρόβλημα είναι να βρίσκεται στην πλευρά ανάγνωσης, καθώς για να μπορέσετε να λάβετε την πραγματική κατάσταση της οντότητας απαιτείται η επανάληψη όλων των συμβάντων.
Σύναψη
Σε αυτό το άρθρο, εξετάσαμε διάφορες προσεγγίσεις για τη δημιουργία αξιόπιστων μηνυμάτων σε κατανεμημένα συστήματα. Υπάρχουν πολλές συστάσεις που θα μπορούσαμε να λάβουμε υπόψη κατά την κατασκευή συστημάτων με αυτά τα χαρακτηριστικά
- Πάντα να αναπτύσσετε ανίκανους καταναλωτές, καθώς η αστοχία του δικτύου είναι αναπόφευκτη.
- Χρησιμοποιήστε προσεκτικά το First-Local-Commit-Then-Publish με σαφή κατανόηση των απαιτήσεων εγγύησης.
- Μην χρησιμοποιείτε ποτέ την προσέγγιση First-Publish-Then-Local-Commit καθώς μπορεί να οδηγήσει σε σοβαρή ασυνέπεια δεδομένων στο σύστημά σας.
- Εάν η υπάρχουσα απόφαση επιλογής βάσης δεδομένων είναι πολύ πιθανό να αλλάξει ή η τεχνική στρατηγική συνεπάγεται την επιλογή της καλύτερης λύσης αποθήκευσης για το πρόβλημα — μην δημιουργείτε κοινόχρηστες βιβλιοθήκες δεσμεύοντας σε λύσεις βάσης δεδομένων όπως το CDC .
- Χρησιμοποιήστε την προσέγγιση των εξερχόμενων συναλλαγών ως τυπική λύση για την επίτευξη τουλάχιστον μίας εγγύησης.
- Σκεφτείτε να χρησιμοποιήσετε την προσέγγιση Ακούστε τον εαυτό σας όταν χρησιμοποιούνται βάσεις δεδομένων No-SQL.
Την επόμενη φορά, θα δούμε ένα πιο πρακτικό παράδειγμα εφαρμογής ενός Συναλλαγών Εξερχόμενων. Βλέπω
εσείς!