Στρατηγικές επανάληψης και ιδιαιτερότητα
1) Γιατί το χρειάζεστε
Στα δίκτυα, οι αστοχίες είναι ο κανόνας: timeouts, παροδικά σφάλματα, flapps δικτύου, υπερφόρτωση. Οι υποχωρήσεις βελτιώνουν την αξιοπιστία μόνο εάν:1. επαναλαμβανόμενη ασφάλεια (idempotent),
2. παρατηρούνται καθυστερήσεις μεταξύ επαναλήψεων,
3. τηρούνται τα όρια/ποσοστώσεις και οι εθισμοί «υγεία».
Ο στόχος είναι ουσιαστικά μια φορά συμπεριφορά στο επίπεδο των επιχειρηματικών δραστηριοτήτων χωρίς ψευδείς λήψεις και αγώνες.
2) Ταξινόμηση της σημασιολογίας παράδοσης
Το πολύ μία φορά: καμία επανάληψη, κίνδυνος απώλειας (υλοτομία, πυρκαγιά και λησμονώ).
Τουλάχιστον μία φορά: τα αντίγραφα είναι δυνατά → απαιτείται η ταυτότητα του καταναλωτή (οι περισσότερες ουρές αναμονής, webhooks).
Αποτελεσματικά μία φορά: τα αντίγραφα είναι δυνατά, αλλά απενεργοποιούνται σωστά (κλειδιά, συναλλαγές, outbox).
3) Πότε να αποσυρθεί και πότε όχι
Η υποχώρηση έχει νόημα: '408', '429' (παρατηρώντας 'Retry-After'), '425' (Too Early), '499' (πελάτης κλειστός στην περίμετρο), '5xx', '504', timeouts δικτύου/breaks, '502' στην πύλη, «επαναφορά σύνδεσης».
Μην αποσυρθείτε χωρίς να αλλάξετε την ερώτηση: '400/ 401/403/404/422'.
Αμφιλεγόμενες περιπτώσεις: '409 Σύγκρουση' (δεν συνήθως retrayim? πρώτα διαβάζουμε το καθεστώς της επιχείρησης/επιβεβαιώνουμε την πρόθεση).
4) Timeouts, backoff και νευρικότητα
4. 1 Κανόνες
Πρώτον, στη συνέχεια ρετρό: κάθε αίτηση πρέπει να έχει «προθεσμία».
Εκθετική εφεδρεία: 'delay _ n = base 2 n', limit 'max _ delay'.
Απαιτείται jitter: προσθήκη τυχαιότητας για την αποσύνδεση «βαρετών συγχρονισμένων κυμάτων».
4. 2 Μοτίβα νευρώσεων
Full jitter: 'sleep = rand (0, base2 n)' είναι η καλύτερη συνολική επιλογή.
Διακοσμημένη νευρικότητα: 'sleep = min (max_delay, rand (base, sleep_prev3))' - για μακροχρόνιους διαλόγους.
Ίση νευρικότητα: 'sleep = base2 n/2 + rand (0, base2 n/2)' - ήπια διακύμανση.
4. 3 Επαναπροσδιορισμός προϋπολογισμού
Περιορισμός της αναλογίας των retrays:- 'retry _ budget _ per _ min = max (α success_rps, floor β)', συνήθως 'α = 0. 1–0. 2`.
- Εάν ο προϋπολογισμός έχει εξαντληθεί, μεταβείτε σε «ανοικτό» διακόπτη αστοχίας/διακόπτη κυκλώματος.
5) Αλληλεπίδραση με τον περιορισμό του ρυθμού και τον διακόπτη κυκλώματος
Σεβαστείτε το 'Retry-After', ' Limit-Reset' και μετρήστε το στο back-off.
Σε υψηλά '5xx '/timeouts - χαμηλότερη συχνότητα επαναπροσδιορισμού και συνολικό νόμισμα.
- Half-open: Επιτρέπει περιορισμένη δειγματοληψία.
- Άνοιγμα: αμέσως απορρίπτει (εξοικονομεί πόρο).
- Κλειστό: συνήθεις εργασίες.
- Στις λειτουργίες γραφής, είναι προτιμότερο να επιστρέφει κανείς 409/503 με μια σαφή υπόδειξη από το να στρίβει επιθετικά retrays.
6) Ιδιαιτερότητα των πράξεων εγγραφής
6. 1 Γενική ιδέα
Οι ίδιες προθέσεις → ένα αποτέλεσμα. Η βάση είναι το κλειδί της ταυτότητας και η αποθήκευση των αρχείων εκτέλεσης.
6. 2 Σύμβαση HTTP
Ο πελάτης στέλνει την επικεφαλίδα:
Idempotency-Key: 7a6b7f9e-2a46-4d0b-9c3a-2b30e1c3c9e3
Idempotency-Key-Expiry: 24h # optional
Εξυπηρετητής:
- Αποταμιεύει (κλειδί, κατάσταση αποτελέσματος, hash σώματος) στην πρώτη επιτυχία
- εάν επαναληφθεί, επιστρέφει την παλιά απάντηση και την επικεφαλίδα 'Idempotency-Replay: αλήθεια'·
- σε περίπτωση σύγκρουσης σώματος (το ίδιο κλειδί, αλλά διαφορετικό ωφέλιμο φορτίο) - '409 Σύγκρουση'.
6. Αποθήκευση και TTL
Πλήκτρο πίνακα/τιμής: 'idempotency _ key', 'request _ hash', 'result', 'status', 'expiry _ at'.
TTL = παράθυρο πιθανών επαναλήψεων και καθυστερημένων παραδόσεων (συνήθως 24-72 ώρες για πληρωμές).
Δείκτες από 'idempotency _ key'; για το υψηλό φορτίο - hash sharding.
6. 4 Παράδειγμα σχήματος (SQL)
sql
CREATE TABLE idempo_store (
key UUID PRIMARY KEY,
req_hash BYTEA NOT NULL,
status INT NOT NULL,
response JSONB NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
expiry_at TIMESTAMPTZ NOT NULL
);
6. Ψευδοκώδικας χειριστής
pseudo handle_write(req):
k = req. headers["Idempotency-Key"]
h = hash(req. body)
rec = idempo_store. get(k)
if rec and rec. req_hash == h:
return rec. status, rec. response, {"Idempotency-Replay": "true"}
if rec and rec. req_hash!= h:
return 409, problem("IDEMPOTENT_CONFLICT")
begin tx result = apply_business_mutation (req) # change status upsert once (idempo_store, key = k, req_hash=h, status = 201, response = result, expiry = now () + 2d)
commit
return 201, result
7) πρότυπα «αποτελεσματικά άπαξ»
Transactional Outbox: καταγραφή ενός επιχειρηματικού γεγονότος και αποστολή μηνύματος από την ίδια συναλλαγή βάσης δεδομένων μέσω του βασικού αναμεταδότη· ο καταναλωτής είναι ταυτόσημος.
Εισερχόμενα/Επεξεργασμένος πίνακας στον καταναλωτή: αποθήκευση 'event _ id' για να αγνοηθούν τα αντίγραφα.
Ακριβώς μία φορά για την Kafka ≠ ακριβώς μία φορά στις επιχειρήσεις: ακόμη και με το EOS παραγωγού/καταναλωτή, η εφαρμοσμένη λογική θα πρέπει να εξακολουθεί να είναι ταυτόσημη.
Αντισταθμιστικές συναλλαγές (Saga): αν τα βήματα αποσυρθούν και προκαλέσουν παρενέργειες, επιστρέφουμε το σύστημα στο αμετάβλητο.
8) Ειδικές περιπτώσεις: πληρωμές και χρηματοπιστωτικές συναλλαγές
Ισχυρή ταυτότητα: Το κλειδί συνδέεται με τη λογική λειτουργίας (π.χ. 'external _ payment _ i ).
Deduplication on PSP - Store 'merchant _ reference' → εάν επαναληφθεί, το PSP θα επιστρέψει το ίδιο αποτέλεσμα.
Retrays «από τον πελάτη»: επιτρέπει μόνο όταν 'Idempotency-Key', διαφορετικά ο κίνδυνος διπλής διαγραφής.
Διαγωνισμός: κλειδαριές «σε λογαριασμό/εργαλείο/σύμβαση» κατά τη διάρκεια της εκτέλεσης· όταν επαναλαμβάνεται, επιστρέφει 409/423.
Παρατηρησιμότητα: idempo _ replay _ total ',' idempo _ conflict _ total '.
9) Webhooks και εξωτερικές προκλήσεις
Υπογραφές HMAC και χρονοθυρίδα. πρώτη επαλήθευση, στη συνέχεια επεξεργασία.
retrays: εκθετική backoff + jitter, 'max _ απόπειρες' και DLQ.
Καταναλωτής - idempotent: 'event _ i table/in-memory cache? η «τακτοποιημένη» σειρά δεν είναι εγγυημένη.
Κωδικοί: 2xx = επιτυχής, 4xx = μη επαναλαμβάνεται, 5xx/timeout = επανάληψη.
10) Ουρές αναμονής και βασικά καθήκοντα
Τουλάχιστον μία φορά εξ ορισμού → τα αντίγραφα είναι αναπόφευκτα.
Αποθήκευση 'task _ i /' event _ id' και κατάσταση εκτέλεσης; με αντίγραφα - το σύντομο μονοπάτι «replay».
DLQ και δηλητηριώδη μηνύματα: απόπειρα μετρητή, καραντίνα, χειροκίνητη ανάλυση.
Ανταγωνιστικά όρια (semaphores) και ευφυείς εργαζόμενοι.
11) Εκδόσεις και «φυσικά» κλειδιά
Φυσικά κλειδιά (αριθμός λογαριασμού + ημερομηνία + αριθμός εγγράφου) αυξάνουν την αντίσταση στην επανάληψη.
Κατά την αλλαγή του σχήματος/έκδοσης, συμπεριλάβετε το κλειδί έκδοσης στο 'Idempotency-Key' or στο hash ερωτήματος.
12) Κεφαλίδες HTTP και κίνητρα προς τον πελάτη
Idempotency-Key, 'Idempotency-Replay', 'Retry-After', 'Prefer: wait = <sec>' (on long operations), 'If-Match '/' ETag' (αισιόδοξες κλειδαριές).
409 για μια σύγκρουση-κλειδί 425/429/503 με το έγκυρο 'Retry-After'.
Για «μακροχρόνιες» λειτουργίες - λήψη ασύγχρονης κατάστασης ('202 Αποδεκτή' + 'Τοποθεσία' ανά πόρο κατάστασης).
13) Σενάρια δοκιμών και χάους
Αρνητικές δοκιμές: διπλή αποστολή, επανάληψη με άλλο σώμα, αποσυγχρονισμός ρολογιού.
Εκτός διαδικασίας: το 't2' προηγείται του 't1'.
Έγχυση χρονοδιαγραμμάτων/' RST '/' EOF ', μισές αιτήσεις (αργή-POST).
Πεσμένη idempotency αποθήκευση → αποτυχημένη-κλειστή συμπεριφορά (καλύτερη αποτυχία από τη διπλή διαγραφή).
14) Μετρήσεις και προειδοποιήσεις
'retries _ total {reason}', 'retry _ budget _ used {route}', 'backoff _ seconds _ bucket'.
'idempo _ replay _ total', 'idempo _ conflict _ total', 'duplicate _ inclused _ total'.
Μοιραστείτε το 409/425/429/5xx ανά δρομολόγιο. p95/p99 «χρόνος επιτυχίας» με υποχωρήσεις.
Ειδοποιήσεις: επαναδιαμόρφωση του προϋπολογισμού, αύξηση των συγκρούσεων ιδεολογίας, ανάπτυξη DLQ.
15) Αντιπατερίδια
Αποσύρετε όλα τα λάθη στη σειρά.
Έλλειψη νευρικότητας → συγχρονισμένα κύματα επαναπροσδιορισμών.
Μακρόβια κλειδιά χωρίς TTL και καθαρισμό.
Σώζοντας το αποτέλεσμα μετά από μια παρενέργεια που διαπράχθηκε (παραβίαση outbox).
Τα αρχεία καταγραφής χωρίς 'trace _ id '/' idempotency _ key' είναι → αδύνατο να δημιουργηθούν.
Επιθετικές παράλληλες αναταξινομήσεις σε λειτουργίες εγγραφής.
16) Κατάλογος ελέγχου ετοιμότητας Prod
- Ενιαία πολιτική: τι retrayim, τι όχι? κωδικοί και κίνητρα πελατών.
- Εκθετική εφεδρεία + πλήρης νευρικότητα; 'retry _ budget' definited.
- Σύμβαση 'Idempotency-Key' + αποθήκευση αποτελεσμάτων με TTL.
- Outbox/Inbox για εκδηλώσεις· DLQ· τα όρια ανταγωνισμού.
- Ενσωμάτωση με διακόπτη κυκλώματος, σεβαστείτε το 'Retry-After'.
- Metrics/alerts by Retray/Duplicate/Conflict.
- Μια σειρά από δοκιμές χάους και εξομοίωση αστοχίας δικτύου.
- Τεκμηρίωση πελατών - παραδείγματα εφεδρειών και καταστάσεων.
17) TL, DR
Οι υποχωρήσεις είναι χρήσιμες μόνο μαζί με την ιδιαιτερότητα. Εισάγετε το 'Idempotency-Key' και την αποθήκευση αποτελεσμάτων, εφαρμόστε εκθετική εφεδρεία με νευρικότητα και ανακατασκευή προϋπολογισμού, σεβαστείτε το 'Retry-After', ενσωματώστε με διακόπτη κυκλώματος. Για εκδηλώσεις - outbox/inbox; για πληρωμές, αυστηρή αποεπένδυση και κλειδαριές. Μετρώνται οι ανατροπές και οι συγκρούσεις, τα αντίγραφα δοκιμών και τα χρονοδιαγράμματα.