אסטרטגיות חזרה ואידמפוטנטיות
1) למה אתה צריך את זה
ברשתות, כשלים הם הנורמה: פסקי זמן, טעויות זמניות, נפילות ברשת, עומס יתר. נסיגות משפרות אמינות רק אם:1. חזור בטוח (אידמפוטנט),
2. עיכובים בין חזרות נצפים,
3. מגבלות/מכסות והתמכרויות ”בריאות” מכובדות.
המטרה היא התנהגות יעילה-פעם אחת ברמה של פעולות עסקיות ללא לקיחות שגויות וגזעים.
2) טקסונומיה של סמנטיקה מסירה
לכל היותר-פעם: אין חזרה, סיכון לאובדן (כריתת עצים, אש-ולשכוח).
לפחות פעם אחת: שכפולים אפשריים = יש צורך באידמפוטנציה צרכנית (רוב התורים, webhooks).
ביעילות-פעם אחת: שכפולים הם אפשריים, אבל משוכפלים נכון (מפתחות, עסקאות, יוצא).
3) מתי לחזור בך ומתי לא
נסיגה הגיונית: ”408”, ”429” (התבוננות ”Retry-After”), ”425” (מוקדם מדי), ”499” (לקוח סגור על ההיקף), ”5xx”, ”504”, זמן רשת/שברים, ”502” בשער, ”איפוס חיבור”.
אל תחזור בך מבלי לשנות את השאילתה: '400/ 401/403/404/422'.
מקרים שנויים במחלוקת: '409 קונפליקט' (לא בדרך כלל מחדש; תחילה אנו קוראים את מצב המבצע/לאשר מחדש את הכוונה).
4) פסקי זמן, חזרה וריגושים
4. 1 כללים
פסק זמן ראשון, ואז רטרו: כל בקשה חייבת להיות ”מועד אחרון”.
גיבוי אקספוננציאלי: ”השהייה _ n = בסיס 2 _ n”, הגבלה ”max _ helief”.
ג 'יטר נדרש: להוסיף אקראיות ל ”גלים סינכרוניים עמומים”.
4. 2 תבניות ג 'יטר
'שינה = רנד (0, base2 ın)' היא הבחירה הכללית הטובה ביותר.
ג 'יטר מעוצב: ”שינה = מין (max_delay, רנד (בסיס, sleep_prev3))” - עבור דיאלוגים ארוכים.
ג 'יטר שווה: ”שינה = base2 än/2 + rand (0, base2 än/2)” - וריאציה רכה.
4. 3 ניסיון מחדש בתקציב
הגבל את יחס המגשים מחדש:- 'retry _ budder _ per _ min = max (= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = בדרך כלל '= 0. 1–0. 2`.
- אם התקציב מותש, תעבור למפסק ”פתוח”.
5) אינטראקציה עם מגבלת קצב ושובר מעגל
כבדו את ”Retry-After”, ”About Limit-Reset” וספרו אותו בגב-off.
בפסקי זמן High '5xx' - להוריד את תדר המגש מחדש וכללי.
- חצי פתוח, מאפשר דגימה מוגבלת.
- פתח: דחייה מיידית (חוסכת משאבים).
- סגור: עבודה רגילה.
- על פעולות כתיבה, עדיף להחזיר 409/503 עם רמז ברור מאשר לסובב מגשים אגרסיביים.
6) אידמפוטנטיות של פעולות כתיבה
6. רעיון כללי 1
אותן כוונות = תוצאה אחת. הבסיס הוא מפתח האידמפוטנטיות ואחסון רשומות ההוצאה להורג.
6. חוזה 2 HTTP
הלקוח שולח את הכותרת:
Idempotency-Key: 7a6b7f9e-2a46-4d0b-9c3a-2b30e1c3c9e3
Idempotency-Key-Expiry: 24h # optional
שרת:
- חיסכון (מפתח, תוצאה = סטטוס, חשיש גוף) בהצלחה ראשונה
- אם חוזר על עצמו, חוזר על התגובה הישנה והכותרת 'Idempotency-Replay: true';
- במקרה של סכסוך גוף (אותו מפתח, אבל מטען אחר) - 'סכסוך 409'.
6. 3 אחסון ו ־ TTL
מפתח טבלה/ערך: "idempotency _ key", "request _ hash", "secure", "status", "experience _ at'.
TTL = חלון של שידורים חוזרים אפשריים ומשלוחים מאוחרים (בדרך כלל 24-72 שעות לתשלומים).
מדדים על ידי 'idempotency _ key'; עבור עומס גבוה - שירידת חשיש.
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. 5 פסאודו ־ קוד של המפעיל
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: הקלטת אירוע עסקי ושליחת הודעה מאותו בסיס נתונים באמצעות ממסר הרקע; הצרכן הוא אידיוטי.
תיבה/טבלה מעובדת אצל הצרכן: שמור את "אירוע _ id' כדי להתעלם משכפולים.
בדיוק-פעם אחת על קפקא בדיוק-פעם אחת בעסק: אפילו עם יצרן/צרכן EOS, היגיון יישומי עדיין צריך להיות אידמפוטנטי.
פיצוי על עסקאות (סאגה): אם הצעדים חוזרים וגורמים לתופעות לוואי, אנו מחזירים את המערכת לאינווריאנט.
8) מקרים מיוחדים: תשלומים ועסקאות כספיות
אידמפוטנטיות חזקה: המפתח מחויב ללוגיקת הפעולה (למשל: 'external _ תשלום _ id'.
Dauplication on PSP - Store 'serchant _ Reference' ac, PSP יחזיר את אותה התוצאה.
מגשים מחדש ”מהלקוח”: לאפשר רק כאשר ”Idempotency-Key”, אחרת הסיכון למחיקה כפולה.
תחרות: מנעולים ”בחשבון/כלי/חוזה” למשך הביצוע; כאשר חוזרים, לחזור 409/423.
תצפיות: metrics 'idempo _ replay _ total', 'idempo _ conflict _ total'.
9) אתרי אינטרנט ואתגרים חיצוניים
חתימות HMAC וחלון זמן; אימות ראשון, לאחר מכן עיבוד.
מגשים מחדש: גיבוי מעריכי + jitter, "max _ trisons' ו ־ DLQ.
צרכן - idempotent: "event _ id' @ table/in-memory cache; סדר ”מסודר” אינו מובטח.
קודים: 2xx = מוצלח, 4xx = לא חוזר, 5xx/timeout = חוזר.
10) תורים ומשימות רקע
לפחות פעם אחת כברירת מחדל. כפילויות הן בלתי נמנעות.
Stork 'tassion _ id '/' event _ id' and everation status; עם כפילויות, הדרך הקצרה ”שידור חוזר”.
DLQ והודעות רעל: נסיון נגד, הסגר, ניתוח ידני.
גבולות תחרותיים (סמאפורות) ועובדים אידיוטים.
11) ורסינינג ומפתחות ”טבעיים”
מפתחות טבעיים (מספר חשבון + תאריך + מספר מסמך) מגבירים את ההתנגדות לחזרה.
בעת שינוי סכימה/גירסה, כלול את מפתח הגרסה ב 'Idempotency-Key' בחשיש השאילתא.
12) כותרות HTTP ומעביר ללקוח
'Idempotency-Key', 'Idempotency-Replay', 'Retry-After', 'העדפה: המתן = <sec>' (על פעולות ארוכות), 'If-match '/' ETag' (מנעולים אופטימיים).
409 לסכסוך מפתח 425/429/503 עם 'Retry-After תוקף'.
עבור פעולות ”ארוכות” - קבלה של מצב אסינכרוני ('202 מתקבל' + 'מיקום' לכל משאב סטטוס).
13) בדיקות ותרחישי כאוס
בדיקות שליליות: שליחה כפולה, חזרה עם גוף אחר,
'ט2' מגיע לפני 't1'.
הזרקת פסקי זמן/RST/EOF, חצי בקשות (איטי פוסט).
Idempotency Axency # Agency Agency (כישלון טוב יותר מאשר מחיקה כפולה).
14) מדדים והתראות
'retries _ total (סיבה)', 'retry _ budder _ used' route ',' backoff _ seconds _ buket '.
'idempo _ replay _ total', 'idempo _ conflict _ tall', 'duplicate _ guided _ tall'.
שתף 409/425/429/5xx על ידי מסלולים; p95/p99 ”זמן להצלחה” עם נסיגות.
התראות: תקציב מגש שרפה, נחשול בקונפליקטים אידמפוטנטיים, צמיחת DLQ.
15) תרופות אנטי ־ פטריות
לחזור על כל הטעויות ברצף.
חוסר עצבנות * גלים סינכרוניים של חזרות.
מפתחות ארוכי חיים בלי טי-טי-אל וניקיון.
שמירת התוצאה לאחר ביצוע תופעת לוואי (הפרת תיבה).
logs ללא ”trace _ id'/idempotency _ key” הם בלתי אפשריים ליצירת.
מגשים מקבילים אגרסיביים על פעולות כתיבה.
16) רשימת מוכנות תומכת
[ ] מדיניות מאוחדת: מה לחזור, מה לא; קודים וקודים של לקוחות.
[ ] Exponental Backoff + jitter מלא; 'retry _ תקציב' מצטיין.
[ ] חוזה 'Idempotency-Key' + אחסון תוצאות עם TTL.
[ ] Outbox/Inbox לאירועים; DLQ; גבולות תחרותיים.
[ אינטגרציה ] עם מפסק מעגל, לכבד ”Retry-After”.
[ ] מטריצות/התראות על ידי ריטריי/שכפול/קונפליקט.
[ ] סדרה של מבחני כאוס וחיקוי כשל רשת.
[ תיעוד לקוחות ] - דוגמאות של גיבוי ומדינאות.
17) TL; DR
נסיגות מועילות רק עם אידמפוטנטיות. הזן 'Idempotency-Key' ואחסון תוצאה, הפעל גיבוי אקספוננציאלי עם jitter ו-retry-Efter, כבוד ”Retry-After”, אינטגרל עם מפסק מעגל. לאירועים - תיבת דוא "ל; לתשלומים, שכפול קפדני ומנעולים. מדידת מגשים וקונפליקטים, כפילויות בדיקה ופסקי זמן.