Redis Cluster: היכן נשברת ההתרחבות תחת עומס
אינסטנס בודד נתקל בשלושה קירות כמעט בו-זמנית. הזיכרון מוגבל לגודל של מכונה אחת: כאשר מערך הנתונים מתקרב למגבלת maxmemory, מופעלת מדיניות פינוי — ונמחקים מפתחות שאף אחד לא תכנן לאבד.
ולצד זה אפקט שני: שמירה ברקע עם fork על נפח גדול מקפיאה את עיבוד הפקודות למאות מילישניות, וזה נראה בגרף ההשהיות, לא בלוגים.
מפתחות חמים מכריעים אחרת. מונה, סשן, ספר עזר שכל הבקשות פונות אליו — חי בחוט אחד — ולא משנה כמה ליבות יש, העומס נופל על חוט אחד. לפרוס מפתח כזה על פני רפליקות לא עוזר: הכתיבה בכל זאת הולכת למאסטר, וקריאה מהרפליקות מחזירה חוסר סנכרון וערכים מיושנים.
הצפת זיכרון מורגשת כמפל, לא ככשל. הפינוי עובר ממפתחות שפג תוקפם למפתחות שרירותיים, חלק מהבקשות מתחילות לפנות ישירות למסד הנתונים, ההשהיות שלו גדלות, ובשיא כבר נופל הכול. בנוסף, מחסור בזיכרון עובר ל-swap — זמן התגובה נמדד בשניות, אבל פורמלית השירות חי.
זה נתפס ברגע שבו שיא העומס חופף לכתיבה: צוואר בקבוק אחד גורר אחריו את האחרים, ואין מאיפה לקחת חזרה למצב הקודם. בדיוק בגלל זה מתכננים התרחבות של Redis מראש, ולא אחרי תקלה.
להלן נבחן כיצד זה נסגר באמצעות מעבר ל-Redis Cluster: שרדינג לפי סלוטים, פיצול מפתחות חמים והתנהגות צפויה בעת כשל של צומת.
מה נותן הקלאסטר: גדילה לפי צמתים וכשל בלי השבתה
ב-Redis Cluster מרחב המפתחות מחולק לסלוטים, וכל מאסטר אחראי על חלקו. כל עוד המפתחות מפוזרים באופן אחיד, הוספת צמתים מעלה את תקרת הפעולות כמעט באופן פרופורציונלי — הנקודה התוחמת עוברת מתהליך אחד לרשת ולעקביות בין הצמתים.
את סכמת המפתחות בודקים לפני ההתרחבות: מפתחות חמים ופעולות על כמה סלוטים בבת אחת אוכלים את התוספת מהר יותר מקצב הוספת הצמתים. זה המקרה שבו התרחבות אופקית של מסד הנתונים נתקלת לא בחומרה, אלא במודל הנתונים.
עמידות הקלאסטר בפני תקלות נשענת על רפליקות: לכל מאסטר יש עותק, וכשהוא נופל, שאר המאסטרים מעלים את הרפליקה בהצבעה. מכלל התפעול יוצא סוג שלם של כשלים — נפילה של צומת אחד כבר לא עוצרת כתיבה ולא דורשת העלאה ידנית מגיבוי עם אובדן הפעולות האחרונות.
זמן ההתאוששות מתקצר מעשרות דקות של עבודה ידנית למעבר אוטומטי תוך שניות. חלון הזמן שבו הכתיבה אינה זמינה מצטמצם, והלקוחות קוראים מחדש את הטופולוגיה וממשיכים לעבוד בלי התערבות התורן.
תפוקת המערכת גדלה גם בזכות הרפליקות: הקריאה מתפזרת בין העותקים, אם האפליקציה מוכנה לכך. לפני השינויים אנחנו מבצעים מדידות — פעולות בשנייה, השהיה באחוזון ה-95, שיעור הכשלים שנסגרו אוטומטית — וחוזרים עליהן אחר כך, כדי שהצמיחה תהיה מדידה ולא רק מוצהרת.
Redis Cluster או רפליקציה: השוואת מצבי עבודה
רפליקציה וקלאסטר פותרים משימות שונות, ולכן בוחרים אותם לפי פרופיל הנתונים, לא לפי «עוצמה». רפליקציה משכפלת את אותו מערך נתונים על כמה צמתים: עמידות בפני תקלות ותפוקת קריאה גדלות, אבל לא הנפח. קלאסטר מוסיף שרדינג — הנתונים מפוזרים בין הצמתים, וגם הכתיבה מתרחבת.
| אפשרות | מתי מתאימה | מגבלות |
|---|---|---|
| רפליקציה עם פיצול מפתחות ידני | הנפח נכנס לצומת אחד, האפליקציה בעצמה יודעת לאן לכתוב | תקרת זיכרון של הצומת, החלפת תפקידים על ידי גורם בורר חיצוני, לוגיקת הפיצול חיה בקוד האפליקציה |
| קלאסטר עם פיזור אוטומטי של סלוטים | הנתונים לא נכנסים לצומת אחד, יש צורך בכתיבה לכל המאסטרים | פעולות עם כמה מפתחות דורשות תג משותף, חלק מהפקודות אינן זמינות, איזון מחדש יוצר קפיצות בהשהיה |
| היברידי: קלאסטר, רפליקות ומסלול קריאה נפרד | דוחות כבדים וייצוא נתונים לא צריכים להכות בצמתי הייצור | תחזוקה מורכבת יותר, יש לעקוב אחר השהיית הרפליקציה והעקביות |
| שרדינג בצד האפליקציה | נדרש שליטה מלאה על מיקום המפתחות | ניתוב ואיזון מחדש — באחריות האפליקציה, שינוי טופולוגיה דורש תוכנית מיגרציה |
הקריטריון המעשי פשוט: אם הנתונים מפסיקים להיכנס לזיכרון של צומת או שכתיבה נתקלת במאסטר אחד — רפליקציה לא פותרת את המשימה. הטעות ההפוכה מתרחשת לא פחות: קלאסטר על נפחים קטנים מביא איתו מגבלות על פקודות ומורכבות תחזוקה בלי רווח. נבחן כיצד לבחור מצב בהתאם לעומס ולפרופיל הנתונים וכיצד לתכנן מעבר ביניהם בלי הפסקה בעבודה.
שלבי הטמעה: מביקורת ועד מסירה לתפעול
הטמעת קלאסטר מתחילה לא בהתקנה, אלא בביקורת פרופיל העומס: אוספים סטטיסטיקה לפי פקודות, יחס קריאות/כתיבות, גודל הערכים, זמן החיים של המפתחות ושיאים יומיים.
הנתונים האלה קובעים כמה צמתים באמת דרושים, היכן יעבור הגבול בין נתונים חמים לקרים ואילו מפתחות אסור לפזר בין צמתים שונים בלי לאבד אטומיות של פעולות.
- ביקורת עומס. אוספים פרופיל תעבורה למחזור מלא — שעות עבודה, חלונות לילה, שיאי דוחות. מתעדים את שיעור הפעולות הכבדות, נפח מערך העבודה והמרווח בזיכרון בכל צומת.
- סכמת פיצול נתונים. מתכננים פריסת מפתחות לפי מקטעים: בוחרים תבנית שמות, מוציאים מפתחות חמים, בודקים שמבנים קשורים נופלים לאותו צומת. בשלב זה קובעים את מספר המקטעים והמרווח לצמיחה.
- טופולוגיה ועמידות בפני תקלות. פורסים צמתים ראשיים ומשניים באזורי זמינות שונים, כדי שכשל של ארון לא ייקח זוג שלם. מגדירים קוורום, פסקי זמן והתנהגות לקוחות בעת מעבר.
- פריסה ומיגרציה. מרימים קונפיגורציה, מעבירים נתונים בלי לעצור את השירות: מעבר הדרגתי של קריאות, ואחר כך כתיבות, עם בקרת אי-התאמות בכל שלב.
- בדיקת עמידות בפני תקלות. מכבים צמתים אחד-אחד ובקבוצות, מודדים את זמן המעבר ואובדן הכתיבות, בודקים את התנהגות האפליקציה תחת עומס. בנפרד מריצים תרחיש של החזרת צומת לפעילות.
- מסירה לתפעול. מוסרים ניטור עם ספים, התראות על ירידת ביצועים, נהלים לעבודות מתוכננות ותיעוד של סכמת הפיצול — צוות הלקוח מנהל את הקלאסטר מכאן והלאה בעצמו.
סדר השלבים אינו מקרי: כל שלב נשען על הנתונים של קודמו, ולכן בעיות נתפסות לפני העלייה לפרודקשן, ולא ברגע השיא.
מה נשאר אצלכם: קונפיגורציות, סכמות, נהלים
אחרי מסירת הקלאסטר לא נשארים אתם עם מאגר זר והסברים בעל פה. את החבילה מוסרים בשלמותה למערכת בקרת הגרסאות שלכם, וכל שינוי בהמשך עובר ביקורת: לפיה הצוות שלכם מרים סביבה מאפס, מוסיף צומת חדש ומשחזר נתונים אחרי כשל של מאסטר — בלי לפנות אלינו.
- קונפיגורציות של כל הצמתים: קבצי עבודה עם מצב קלאסטר מופעל, פסקי זמן, מגבלות זיכרון ומדיניות פינוי מפתחות, עם הערות — למה נבחר דווקא הערך הזה ומה יישבר אם ישתנה.
- מפת טופולוגיה: פיזור הסלוטים בין המאסטרים, שיוך הרפליקות, אזורי רשת ונקודות כשל על גבי סכמה אחת שאפשר להראות למשמרת התורנית.
- מדיניות גישה: הפרדה לפי ACL — מה כל שירות קורא וכותב, חשבונות נפרדים לניטור ולפעולות ניהול, סדר החלפת סיסמאות.
- סקריפטים לגיבוי: יצירת צילומי מצב מהרפליקות לפי לוח זמנים, בדיקת שלמות, ייצוא מחוץ לקלאסטר ושחזור בדיקה קבוע.
- נוהל תחזוקה: מעבר מתוכנן של מאסטר, הוספת צומת, איזון מחדש של סלוטים ועדכון בלי השבתה — עם חלונות וקריטריונים למוכנות.
- סדר פעולות באירוע: מה לבדוק קודם, איך להבדיל בין צומת כשל לבין ירידת ביצועי רשת, מתי להתערב ידנית ומתי להמתין למעבר אוטומטי.
- תיעוד הקלאסטר: החלטות ארכיטקטוניות והסיבה שהן כאלה, יומן שינויים, צ'קליסט קבלה שלפיו אתם מאשרים את העבודה.
מקרה בוחן: איך הקלאסטר הסיר תקלות בעומס שיא
אינסטנס Redis אחד החזיק גם מטמון, גם תורי משימות וגם סשנים של משתמשים. בשיא — מבצע מכירות, דיוור המוני, כניסה בוקרית לאפליקציה — זרם הפעולות גדל פי שלושה, הצומת נתקל בתקרה, ואיתו נעצרו תרחישים שאין להם קשר למטמון. בעיני הלקוח זה נראה לא כ״איטי״, אלא כ״לא עובד״.
הניתוח הראה שלושה צווארי בקבוק: זיכרון לנתונים עם פרגמנטציה, עיבוד פקודות בליבה אחת והיעדר מוחלט של רפליקות. לא היה צומת רזרבי — כשהתהליך נפל, השירות לא עלה מעצמו, והתורן עשה זאת ידנית.
מה שינו
פרסנו קלאסטר מכמה צמתים ראשיים עם רפליקות, פיזרנו את המפתחות לפי סלוטים והעברנו את התורים לקבוצת צמתים נפרדת, כדי שפעולות כבדות לא ידחקו החוצה סשנים של משתמשים. ספריות הלקוח הועברו למצב עבודה לפי טופולוגיית הקלאסטר: כשמאסטר מתחלף, החיבור נבנה מחדש בלי שינויים באפליקציה.
מדדים לפני ואחרי
- שיעור הכשלים בעומס שיא: 12% מהבקשות עד אפס — לא נותרו פעולות לא זמינות בשיא.
- זמן התאוששות אחרי יציאת צומת: 30-40 דקות ידניות עד העלאה אוטומטית של הרפליקה ומעבר תוך שניות.
- תקרת הפעולות: הצומת הבודד הפסיק להיות המגביל — הוספת צומת מגדילה את התפוקה פי כמה.
- התנהגות השירות באובדן צומת: במקום כשל מלא — ירידת ביצועים קצרה וקריאה מחדש של חלק מהמפתחות ממסד הנתונים.
מה לעשות אם האפליקציה כבר עובדת עם שרת בודד?
שרת בודד נתקל לא בכשלים, אלא בתקרה: מערך העבודה תופס זיכרון, רפליקה מצילה מנפילה, אבל לא נותנת מקום לצמיחה. כל עוד יש מרווח, דוחים את המעבר, וכשהוא נגמר — מעבירים בחופזה, ברגע הכי פחות מתאים. לכן מתכננים את המיגרציה מראש ומבצעים אותה בלי לעצור את השירות.
קודם כול מיפוי: אילו מפתחות חיים זמן רב, היכן פעולות נוגעות בכמה מפתחות בבת אחת, אילו מבנים אסור לפזר בין צמתים. פקודות מרובות-מפתחות וסקריפטים דורשים שמפתחות קשורים ישבו על צומת אחד — אחרת כותבים אותם מחדש עם תגי האש משותפים. זה החלק היחיד במעבר שבאמת דורש שינויים בקוד האפליקציה.
את הנתונים מעבירים ברקע: יוצרים דאמפ מהשרת הבודד, טוענים אותו לקלאסטר, ומפזרים את המפתחות לפי טווחי סלוטים. לאחר מכן מפעילים כתיבה כפולה — האפליקציה כותבת גם לאינסטנס הישן וגם לקלאסטר, וקוראת עדיין מהישן. ההעברה מתבצעת על מערכת חיה, והפער בין העותקים אינו עולה על השהיה של פעולה אחת.
שלמות בודקים בהשוואת מפתחות וערכים לפי מדגם, ואז מריצים זרם קריאה בצל אל הקלאסטר ומשווים את התשובות לשרת הבודד. כל עוד יש אי-התאמות, לא מבצעים מעבר: תאימות לאחור של הלקוחות מובטחת — הם כבר יודעים לפעול לפי הפניות בין צמתים, אבל עובדים לפי הכתובת הישנה.
תוכנית נסיגה — דגל בקונפיגורציה: הוא מחזיר את הקריאה לשרת הבודד, שנשאר מחומם ומקבל את כל הכתיבות. אם אחרי המעבר עולה שיעור השגיאות או זמן התגובה, הדגל מוסר תוך שניות, והשירות ממשיך לעבוד במסלול הקודם.
ספקות טכניים: כשל בצמתים, מעבר ותאימות
לפני מסירת הקלאסטר אנחנו מפרקים את מה שבדרך כלל עולה בקבלה: התנהגות באובדן צומת, היקף השינויים באפליקציה, דרישות רשת ומה נשאר בצד שלנו אחרי המסירה.
מה יקרה באובדן צומת?
לכל מאסטר מוגדרת רפליקה, והסלוטים ממופים מחדש אוטומטית תוך שניות: הלקוח מקבל הפניה וחוזר על הבקשה. הנתונים נשמרים אם הרפליקה הספיקה להסתנכרן, ולכן אנחנו פורסים את הצמתים באזורי כשל שונים.
האם יהיה צורך לשנות קוד?
דרייברים עדכניים עובדים עם קלאסטר, ולכן השינויים בקוד מצטמצמים לקונפיגורציה: רשימת צמתים במקום כתובת אחת, מצב קלאסטר, פסקי זמן וניסיונות חוזרים. בנפרד בודקים פעולות על כמה מפתחות בבת אחת — מחוץ לסלוט אחד הן לא עוברות, ומקומות כאלה מעבירים לתגי האש.
מה הדרישות מהרשת?
לצמתים נדרשת קישוריות ישירה דרך פורט שירות והשהיה אחידה: חילופי מצב מתנהלים כל הזמן, ואובדן חבילות גורם לבחירות מאסטר שגויות. מקבעים כתובות סטטיות, מוציאים תרגום כתובות בין הצמתים, וקובעים ספי בדיקת תקינות עם מרווח.
מה כלול בתחזוקה אחרי המסירה?
מוסרים קונפיגורציה, מפת סלוטים ונוהל לפעולות אופייניות: הוספת צומת, מעבר מתוכנן, שחזור מעותק, עדכון רפליקה אחת בכל פעם. מהנדסי הלקוח מריצים את התרחישים בסביבת בדיקה יחד איתנו, ולכן מכאן והלאה ההתרחבות נעשית בכוחות עצמם.
נדבר על המשימה: מה דרוש כדי להתחיל ולהעריך
הערכת פרויקט לפריסת Redis Cluster לוקחת פחות זמן ככל שנתוני הפתיחה מדויקים יותר. להלן מה שנדרש מכם כדי שנחזור עם תוכנית עבודה ולוח זמנים, ולא עם שאלות הבהרה בעוד שבוע.
- פרופיל עומס: פעולות בשנייה בשיא ובממוצע, שיעור הקריאה והכתיבה, גודל ערך אופייני — מזה תלוי מספר הצמתים והמרווח בזיכרון.
- הסכמה הנוכחית: אינסטנס בודד, מאסטר עם רפליקות או כבר קלאסטר, אילו אפליקציות וספריות לקוח מחוברות אליו.
- צמיחה צפויה: כיצד העומס ונפח הנתונים ישתנו בתוך חצי שנה — מקצים מרווח כדי לא לבנות מחדש את הקונפיגורציה מיד אחרי ההשקה.
- חלון תחזוקה: מתי מותרת הפסקה קצרה בכתיבה, ומתי המעבר צריך לעבור בלי שהמשתמשים ירגישו.
- דרישות התאוששות: זמן ההשבתה המותר בעת כשל של צומת והאובדן המותר של הכתיבות האחרונות.
- תשתית והרשאות גישה: כמה מכונות זמינות, האם יש חלוקה לאזורים, מי מצד הלקוח מאשר שינויים ואילו הרשאות דרושות למהנדסים שלנו.
בתמורה אתם מקבלים תוכנית עבודה לפי שלבים, סכמת פריסת צמתים עם כללי עמידות בפני תקלות ותרחיש מעבר המותאם לחלון התחזוקה שלכם. ככל שמסכימים מוקדם יותר על חלון התחזוקה ודרישות ההתאוששות, כך נמוך יותר הסיכון שיהיה צורך לתכנן את העברת הנתונים פעמיים.







