Retries - מנגנון התאוששות או מכפיל נזק
Retries - מנגנון התאוששות או מכפיל נזק
אחרי שקבענו Timeout, המערכת עומדת מול שאלה שנראית כמעט אוטומטית:
הבקשה נחתכה - האם מנסים שוב?
האינטואיציה אומרת שכן. ההיגיון נראה פשוט: אולי זו הייתה תקלה רגעית, אולי בפעם הבאה זה יעבוד.
אבל כאן בדיוק מתחילה הבעיה.
Retry אינו תיקון - הוא הכפלה
Retry אינו “להמשיך מאיפה שהפסקנו”. הוא יצירת בקשה חדשה.
כל Retry:
- צורך משאבים נוספים
- נכנס שוב לתור
- מתמודד עם אותם תנאי עומס
- ולעיתים פוגש מערכת במצב גרוע יותר מקודם
אם הבעיה המקורית נבעה מעומס - Retry אינו פותר אותה. הוא מעמיק אותה.
Retry amplification
כשל קטן אחד יכול להפוך לאירוע רחב:
בקשה אחת נתקעת → Timeout מפעיל Retry → עשר בקשות הופכות לעשרים → העומס מוכפל → Latency עולה → ו-Timeouts נוספים מופעלים
זהו Retry amplification: תגובה שמגדילה את הבעיה שאותה ניסתה לפתור.
המערכת אינה נופלת בגלל הכשל - אלא בגלל התגובה לכשל.
למה Retries נראים “נכונים” בזמן תכנון
כי הם עובדים יפה:
- בבדיקות
- בעומס נמוך
- ובתקלות נקודתיות
אבל פרודקשן אינו מעבדה.
במערכת חיה:
- כשלי רשת אינם אחידים
- עומס אינו מתפזר באופן שווה
- ורכיבים נופלים יחד, לא לבד
Retry שמתאים לתקלה מקומית מסוכן בתקלה מערכתית.
Exponential backoff - לא פתרון קסם
Exponential backoff הוא מנגנון Retry שבו כל ניסיון חוזר מתבצע אחרי המתנה ארוכה יותר מהקודמת.
לדוגמה:
- ניסיון ראשון - מיד
- ניסיון שני - אחרי 100 מילישניות
- ניסיון שלישי - אחרי 200
- אחריו - 400, 800, וכן הלאה
כלומר, הזמן בין ניסיונות גדל בצורה מעריכית.
הרעיון פשוט: לא להציף את המערכת בניסיונות חוזרים צפופים, ולתת לה “מרווח נשימה” כדי להתאושש.
וזה אכן עוזר.
Backoff:
- מאט את קצב ה-Retries
- מפזר אותם לאורך זמן
- ומפחית עומס מיידי ברגע של כשל
אבל כאן בדיוק נמצאת המגבלה שלו.
למה זה לא פותר את הבעיה העקרונית
Exponential backoff עדיין מניח דבר אחד: שבסופו של דבר - כדאי לנסות שוב.
אם המערכת בצד השני:
- נמצאת בעומס מתמשך
- סובלת מצוואר בקבוק מבני
- או פשוט אינה זמינה
גם Retry איטי, עם המתנה הולכת וגדלה, הוא נזק מצטבר.
הוא:
- ממשיך לצרוך משאבים
- ממשיך להחזיק State
- וממשיך להוסיף עומס עתידי
הבעיה לא נעלמה - היא רק נדחתה.
Retry בלי הקשר הוא הימור
Retry צריך לענות על שאלה אחת בלבד: האם יש סיכוי סביר שהניסיון הבא יצליח יותר מהקודם?
אם התשובה אינה ברורה - Retry הוא הימור.
והימורים, בקנה מידה גדול, נוטים להפסיד.
מתי לא לנסות שוב
יש מצבים שבהם Retry הוא הדבר הגרוע ביותר שאפשר לעשות:
- כשהכשל נובע מעומס
- כשהמערכת בצד השני מאותתת “אני מתקשה”
- וכשאין גבול ברור למספר הניסיונות
במצבים כאלה, ויתור מהיר עדיף על התמדה עיוורת.
המשל
אפשר לחשוב על דלת שלא נפתחת.
אם דופקים שוב מיד - מעמיסים על מי שבפנים.
אם מחכים רגע - אולי יתפנה.
אבל אם ברור שהדלת חסומה - להמשיך לדפוק שוב ושוב רק יוצר רעש ולחץ.
Retry חכם יודע מתי להפסיק.
Retry כבחירה מערכתית
כמו Timeout, Retry אינו החלטה טכנית בלבד.
הוא קובע:
- מי סופג את הכשל
- כמה עומס מותר לייצר כדי “לנסות שוב”
- ואיפה עובר הגבול בין התאוששות לפגיעה
מערכת יציבה אינה שואלת “איך לנסות שוב” - אלא “מתי לא”.
מבט קדימה
Retries ו-Timeouts הם רק ההתחלה.
גם מערכת שמתנהגת יפה בבקשות בודדות עלולה להישבר כשהעומס מגיע בגלים.
בחלק הבא ניכנס לשאלה אחרת לגמרי: לא למה מערכות נשברות בעומס - אלא למה הן נשברות דווקא בשינויים חדים.
בפוסט הבא נעסוק ב-Load Spikes, ולמה “יש לנו מספיק capacity” הוא אחד המשפטים המסוכנים בפרודקשן.
📚 פוסטים נוספים בסדרה: כשהתקשורת נשברת
- חלק 0 כשהתקשורת נשברת - הנדסה תחת עומס, כשל ואי-ודאות
- חלק 1 הנחת היסוד המסוכנת - הרשת אמינה "ברוב הזמן"
- חלק 2 Timeouts - ההחלטה הקשה ביותר בתקשורת
- חלק 4 Load אינו אויב - Spikes כן
- חלק 5 Backpressure - כשלא אומרים "כן" לכול
- חלק 6 Queue אינו פתרון - הוא התחייבות
- חלק 7 Ordering - למה סדר הוא מותרות יקרות
- חלק 8 Idempotency - לתכנן כאילו הכול יישלח פעמיים
- חלק 9 Consistency מול Availability - לא תיאוריה, אלא בחירה יומיומית
- חלק 10 RPC, Messaging, Streaming - שלוש פילוסופיות תקשורת
- חלק 11 Stateless זה לא שאין State - זה איפה הוא נמצא
- חלק 12 תקשורת כמשקפת תרבות הנדסית
- חלק 13 מערכות שמחזיקות - לא בגלל שהן חכמות, אלא בגלל שהן צנועות
- חלק 14 מה למדנו - מפת הדרך של הסדרה כולה