הגדרת תור הודעות (Redis Streams) לתשתית DevOps

עומס שיא הופך תור הודעות לצוואר בקבוק: משימות מצטברות, שירותים מאבדים אירועים. אנו מגדירים תור הודעות מבוסס Redis Streams כפתרון מלא — מתכנון ועד נהלי מסירה. לאחר ההטמעה זרימת האירועים מעובדת ביציבות גם בשיא, ופעולות ידניות מוחלפות באוטומציה.

היכולות שלנו:

שאלות נפוצות

העבודות האחרונות

  • פיתוח אפליקציית ווב עבור FEEDME
    פיתוח אפליקציית ווב עבור FEEDME
    1359
  • פיתוח חנות מקוונת לחברת FURNORO
    פיתוח חנות מקוונת לחברת FURNORO
    1330
  • עיצוב לוגו לחברת B2B Advance
    עיצוב לוגו לחברת B2B Advance
    776
  • פיתוח אפליקציית ווב עבור Enviok
    פיתוח אפליקציית ווב עבור Enviok
    1077
  • פיתוח לוגו חברת AIDER
    פיתוח לוגו חברת AIDER
    1022
  • פיתוח CRM עבור Chasseurs
    פיתוח CRM עבור Chasseurs
    1113

תור הודעות על Redis Streams: צווארי בקבוק תחת עומס

תור הודעות על Redis Streams לעיתים רחוקות נשבר מיד. הכשל הראשון מתגלה בשיא: הצרכן לוקח חבילת רשומות במסגרת הקבוצה ומסתיים באמצע — הודעות שלא אושרו נשארות מוצמדות אליו. עד שצרכן אחר יקרא אותן מחדש לפי זמן ההשבתה, האירועים האלה אינם מעובדים כלל, אף שבמבט חיצוני התור נראה שקט.

צוואר הבקבוק השני — כפילויות. הבטחת המסירה כאן היא לפחות פעם אחת: כל פסק זמן של אישור או חלוקה מחדש של רשומות מחזירים את ההודעה לעבודה שוב. בלי אידמפוטנטיות לפי מזהה הרשומה זה מוביל לחיובים כפולים, להודעות חוזרות ולמונים שלא מסתדרים.

השלישי — השהיית העיבוד. כל עוד הצרכנים אינם עומדים בקצב הזרם, הזרם גדל מהר יותר משמספיקים לפרק אותו, והפיגור של הקבוצה מפסיק להיות ליניארי. הוספת צרכנים עוזרת עד גבול מסוים: מעבר לכך העיבוד נתקע באישורים, שהופכים בעצמם לנקודה חמה.

הרביעי — אובדן הודעות בשיאים. אם אורך הזרם נחתך באופן מקורב, תחת עומס החיתוך מספיק להדיח רשומות שטרם נקראו. אותה תוצאה נובעת מאישור לפני העיבוד בפועל ומכשל של הצומת הראשי בלי המתנה לכתיבה על הרפליקה.

כל ארבעת הכשלים ניתנים לשחזור ומאובחנים לפי סימנים מוגדרים: רשימת אלה שלא אושרו, הפיגור של הקבוצה, זמן ההשבתה של הצרכן, שיעור העיבודים החוזרים. בהמשך נפרט כיצד זה נסגר ברמת התצורה.

מה משתנה בעבודת השירותים לאחר הטמעת התור

תור על Redis Streams מעביר את חילופי האירועים ממצב «שלחתי ואני מקווה» למצב עם אישור מסירה. במקום קריאות ישירות בין שירותים מופיע חוצץ ששורד הפעלה מחדש של המעבד, והעומס מתחלק בין כמה צרכנים בתוך הקבוצה.

  • תפוקה. קריאה בחבילות במקום בקשות בודדות וצרכנים מקבילים בקבוצה אחת נותנים קצב עיבוד אחיד: השיא נבלם בחוצץ, ולא בכשלים של השירות.
  • זמן ההתאוששות לאחר כשל של צומת. רשומות שלא אושרו נשארות ברשימת ההמתנה, ולאחר הפעלה מחדש עוברות לצרכן חי — ההתאוששות נמשכת שניות, בלי פירוק ידני.
  • שיעור האירועים שאבדו. אישור מסירה ומסירה חוזרת מסירים סוג שלם של כשלים: אירועים אינם נעלמים בנפילת המעבד ואינם משוכפלים בשליחה חוזרת.
  • השבתה של השירות. אפשר לעצור צרכן לצורך עדכון — האירועים מצטברים בתור ומפורקים לאחר העלייה, וחלון תיאום נפרד כבר אינו נדרש.
  • סוג הכשלים. במקום אובדן הזמנות נשארים כשלים הפיכים: השהיית עיבוד, גידול בעומק התור, ניסיונות חוזרים. הם מטופלים בלי התערבות ידנית.
  • ניטוריות. עומק התור, הפיגור של הקבוצות ומספר הרשומות שלא אושרו נראים במטריקות — את ההידרדרות מזהים לפני שהמשתמש רואה אותה, והבדיקה «האם הכול הגיע» יוצאת מן העבודה הידנית.

אפשרויות פריסה של התור: השוואה בין גישות טכניות

מצב הפריסה קובע לא רק את עמידות הכשלים, אלא גם כיצד מתנהגים האישורים, המסירה החוזרת והגידול של היומן. צומת בודד של Redis Streams מחזיק נתונים של תהליך אחד — התנעה מהירה, אך אתחול של המארח עוצר גם את הפרסום וגם את העיבוד. קלאסטר ושירות מנוהל מסירים את התלות הזו, ומוסיפים מגבלות על מספר הצמתים ועל הפקודות הזמינות.

כדאי להשוות את האפשרויות לפי שלושה צירים: באיזו מהירות התור מתאושש לאחר כשל של צומת, כמה נתונים הוא מחזיק בלי צניחה בזיכרון, וכמה עבודה ידנית דורש התפעול.

אפשרות מתי מתאימה מגבלות
צומת בודד עומס קטן, משימות במסגרת אחת, השבתה לצורך הפעלה מחדש קבילה אין מעבר אוטומטי: כשל של המארח עוצר את זרימת המשימות
קלאסטר עם רפליקציה סביבת ייצור שבה השבתה ארוכה מדקות אינה קבילה נדרשים לפחות שלושה צמתים, תצורה אחידה ופיקוח על הפיגור של הרפליקות
שירות מנוהל נדרשת עמידות כשלים בלי תורנים ובלי עדכונים ידניים פחות שליטה על הפרמטרים, סט פקודות מצומצם יותר, תלות בספק
תצורה היברידית זרמים קריטיים — בקלאסטר, משניים — לצד האפליקציה קשה יותר לראות תמונה שלמה, נדרשים כללים אחידים וניטור

מעבר בין המצבים אינו דורש לכתוב מחדש את קוד הצרכנים: משתנה כתובת החיבור ומדיניות השמירה, בעוד קבוצות הצרכנים והאישורים עובדים באותו אופן. לכן התחלה על צומת בודד אינה סוגרת את הדרך לקלאסטר — את המצב מחליפים כשמופיעה דרישה לרציפות.

הטמעת Redis Streams: שלבי העבודה ההנדסית

את הטמעת Redis Streams מתחילים בביקורת, ולא בתצורה. תחילה צריך לראות את זרמי הנתונים בפועל: מי מפרסם אירועים, מי קורא אותם, אילו תורים כבר פועלים והיכן ההודעות אובדות בעת כשל של צרכן. בלי המספרים האלה, מערך התורים הופך לניחושים, וזמן החיים של ההודעות ומספר הקבוצות נבחרים באקראי.

  1. ביקורת זרמי הנתונים. אוספים רשימה של מפרסמים וצרכנים, מודדים את תדירות האירועים ומוצאים מקומות שבהם כיום פועלים סקירת בסיס נתונים או קריאות סינכרוניות במקום תור.
  2. תכנון מערך התורים. קובעים את מספר הזרמים, את זמן החיים של ההודעות, את קבוצות הצרכנים ואת כללי אישור העיבוד, וכן את התנהגות המערכת כאשר הקורא אינו זמין.
  3. תצורה. פורסים Redis Streams בתצורה עמידת כשלים, מגדירים מדיניות שמירה ומגבלות זיכרון, מפעילים מטריקות של פיגור קבוצות הצרכנים והתראות על גידול בהודעות שלא עובדו.
  4. בדיקה תחת עומס. מריצים זרם שיא, ניתוק קשר עם הצרכן והפעלה מחדש של צומת: בודקים אם העיבוד מתאושש בלי אובדן אירועים ובכמה זמן מפורק התור שהצטבר.
  5. הגירת זרמים. מעבירים מפרסמים וצרכנים בזה אחר זה, משאירים את הערוץ הישן כגיבוי, ומשווים את מספר האירועים שעובדו בשני המסלולים.
  6. מסירה לתפעול. מוסרים תיעוד, תרשימי תורים, לוחות ניטור ותקנון פעולות בעת תקלה, ומקיימים הדרכה למשמרת התורנית.

מדיניות גישה, תצורות ותקנונים למסירה

תור הודעות על Redis Streams בלי כללים מתועדים הופך במהירות לתיבה משותפת: כל שירות כותב לכל זרם, ובבירור תקלה אי אפשר לשחזר מי קרא ומה. לכן יחד עם התצורה אנו מוסרים ללקוח ערכת ארטיפקטים — בכל אחד מהם נראה מה תועד וכיצד לאמת אותו.

  • תצורת הברוקר — קובצי הגדרות עם מגבלות זיכרון, מדיניות הדחה ופסקי זמן; בנפרד מסומן מה משתנה בזמן ריצה ומה דורש הפעלה מחדש.
  • מפת הזרמים וקבוצות הצרכנים — מפה: מי כותב, מי קורא, איזו קבוצה אחראית לעיבוד חוזר והיכן מצטבר מה שלא עובד.
  • הפרדת הרשאות — חשבון נפרד לכל שירות, הרשאות רק לזרמים שלו; גישת השירות מופרדת מן הגישה הניהולית.
  • מדיניות גישה — אילו כתובות ורשתות מותרות, האם הצפנת הערוץ מופעלת, וכיצד מונפקים ומבוטלים פרטי הגישה.
  • תיעוד — טופולוגיה, ייעוד של כל זרם, התנהגות בעת הצפה, סדר החיבור של צרכן חדש.
  • תקנון תפעול — מה בודק התורן, ספי הפעלה של ההתראות, פעולות כאשר צומת אינו זמין או כשגדל מספר ההודעות שלא עובדו.
  • גיבוי וסבב החלפת גישות — מה מגובים ובאיזו תדירות, כיצד לאמת נקודת שחזור תקינה, וכיצד לבטל מפתחות.

את הערכה עוברים יחד עם מהנדסי הלקוח: מריצים ביטול גישה ושחזור מגיבוי, כדי שהתקנון ייבדק בפועל ולא רק ייכתב. בהמשך הצוות משנה את התצורה ומחבר צרכנים חדשים בעצמו.

מקרה בוחן: תור תחת עומס שיא לפני ואחרי הבנייה מחדש

הפרויקט — שירות לעיבוד בקשות, שבו עומס השיא גבוה פי כמה מהממוצע. התור החזיק את האירועים בזיכרון התהליך: בהפעלה מחדש של הצרכן, בקשות שלא עובדו אבדו לבלי שוב, וצרכן שנתקע לא החזיר את ההודעות שלקח — אותן חילצו ידנית מתוך הלוגים.

העברנו את העיבוד ל-Redis Streams עם קבוצות צרכנים ואישור: האירוע חי ביומן עד שמאשרים אותו, וצרכן תקול מוסר את ההודעות שלו לשכנים בקבוצה.

מדד לפני אחרי
אובדן אירועים בהפעלה מחדש עד כמה אחוזים בשיא אירועים מאושרים אינם אובדים
השהיית עיבוד הבקשה גדלה יחד עם התור נשארת אחידה בשיא
התאוששות לאחר צרכן שנתקע פירוק ידני, עשרות דקות החזרה אוטומטית בתוך דקה
סקיילינג לקראת שיא הפעלה ידנית של עותקי המעבד מספר הצרכנים משתנה בלי עצירה

השינויים נגעו בשלושה מקומות. האישור מסיר אירוע רק לאחר עיבוד מוצלח, ולכן נפילה של המעבד אינה משמעה עוד אובדן בקשה. הודעות שלא אושרו מוחזרות לצרכן אחר לפי פסק זמן — את התקועים מפרק התור עצמו.

היומן מוגבל במספר האירועים האחרונים, הזיכרון אינו גדל ללא גבול, וחזרה לסט המעבדים הקודם נשארת אפשרית.

מה לעשות אם התור כבר פרוס ופועל

קיומו של תור פעיל על Redis Streams אינו סיבה לכתוב אותו מחדש מאפס. תחילה בודקים כיצד הוא בנוי: אילו זרמים קיימים, מי קורא אותם ובאיזו מהירות, כמה הודעות נשארות בלי אישור ומה קורה במסירה חוזרת. ברוב המקרים צוואר הבקבוק אינו במאגר הזרמים עצמו, אלא בהיעדר אישור עיבוד ובחוסר הגבלת אורך.

השלמה ממוקדת סוגרת זאת בלי עצירה: מפעילים אישור עיבוד, מגדירים גודל מרבי לזרם עם חיתוך מקורב, מפרקים הודעות שנתקעו לפי פסק זמן ומעבירים אותן לזרם נפרד של מורעלות. תבנית ההודעות ושמות הזרמים אינם משתנים — הצרכנים הקיימים ממשיכים לעבוד בלי שינויים, ולכן הגירה ככזו אינה נדרשת.

אם ההיגיון דורש עיבוד מחדש, מרימים מסלול מקביל: מעבד חדש קורא את אותם זרמים בקבוצת צרכנים משלו, והנוכחי ממשיך לעבוד. את הפער בודקים לפי מונים של הודעות שעובדו ונדחו; כל עוד השוויון לא אושר, המסלול הישן נשאר הראשי, והחזרה לאחור מסתכמת בניתוק החדש.

מעבר מדורג מתבצע זרם אחד בכל פעם: מחליפים את קבוצת הצרכנים, עוקבים אחר השהיית העיבוד ואחר עומק הזרם, ורק לאחר חלון יציב מסירים את הקוד הישן. עבודה בלי השבתה מובטחת בכך ששתי הגרסאות קוראות מאותו מאגר, וההודעות שלא אושרו נשארות זמינות לצרכן החדש.

היקף העבודה תלוי במספר הזרמים, הצרכנים ובהשהיית העיבוד המותרת — ומכך נבנית תוכנית ההגירה.

ספקות טכניים: השהיות, אובדנים וסקיילינג

ספקות לגבי האמינות צפים כבר בקבלה: צריך להסביר ללקוח מה יקרה בנפילה של צרכן או בגידול פי כמה של הזרם. להלן תשובות למה שנבדק לרוב לפני העלאה של תור על Redis Streams לסביבת הייצור.

מה יקרה אם הצרכן נפל באמצע העיבוד?

ההודעה אינה נעלמת עד שהצרכן מאשר את העיבוד: היא נשארת ברשימת אלה שלא עובדו, ולאחר הפעלה מחדש עוברת לבא בתור בקבוצה. את סף ההמתנה לאישור מגדירים כך שהודעה שנתקעה תחזור לעבודה מעצמה, ולא תמתין להתערבות ידנית.

האם כפילויות בלתי נמנעות?

מצב «לפחות פעם אחת» מתיר חזרה אם האישור לא הגיע. זה נסגר באידמפוטנטיות של המעבד: מפתח הפעולה נרשם במאגר, מעבר חוזר רואה אותו ואינו מבצע את הפעולה פעמיים. בנוסף — מונה ניסיונות והעברה לתור הבעייתיים לאחר מספר חזרות מוגדר.

האם סדר ההודעות נשמר?

סדר קפדני נשמר בגבולות זרם אחד. אם הוא נדרש לפי כל ישות — הזמנה, חשבון, מכשיר — מפזרים את האירועים לפי מפתח הישות: בתוך הזרם הרצף אינו מופר, וישויות שונות מעובדות במקביל.

כיצד לדעת שהפתרון יעמוד בגידול העומס?

בדיקות עומס מתבצעות על פרופיל שמשחזר את סביבת הייצור: זרם שיא, שיעור החזרות, עצירה של צרכן אחד. לפי התוצאות רואים היכן מפסיקה התפוקה לגדול — עד הסף הזה מוסיפים צרכנים לקבוצה, והתור עובר סקיילינג בלי לכתוב מחדש את הקוד.

בואו נדון במשימה: ממה נתחיל ומה נציע

כדי שההערכה תתבסס על עובדות ולא על השערות, מתחילים בנתוני הפתיחה. עבור זרמי Redis Streams שני דברים קריטיים: כיצד האירועים נולדים ובאיזו מהירות הצרכנים מפרקים אותם — מכך תלויה תצורת הזרמים וגם היכן יופיעו כשלים.

  • מהם האירועים ומי קורא אותם: רשימת הזרמים, קבוצות הצרכנים, סדר העיבוד הצפוי וההשהיה המותרת.
  • פרופיל העומס: תדירות ממוצעת ותדירות שיא, גודל ההודעה, תנודות יומיות — מכך נגזרים הגבלת אורך הזרם ומדיניות ההדחה של רשומות ישנות.
  • דרישות אמינות: האם אובדן הודעה קביל, האם נדרשת מסירה חוזרת של תקועים, מה נחשב כשל סופי ולאן עוברת הודעה כזו.
  • היגיון הצרכנים: האם קיים סימן פעולה להגנה מפני חזרות, כיצד בנויים המעבדים וכיצד הם שורדים הפעלה מחדש.
  • תשתית וגישות: זירת האחסון, מצב שמירת הנתונים לדיסק, יתירות, מגבלות רשת וחלונות תחזוקה.
  • ניטוריות: אילו מטריקות נחשבות למרכזיות — גידול בפיגור לפי קבוצות, שיעור ההודעות שלא אושרו — ולאן צריכות להגיע ההתראות.
  • מגבלות קיימות: דרישות אבטחה, תקנונים פנימיים, תאימות לסטאק שכבר בשימוש.

בתמורה תקבלו את הרכב העבודה לפי שלבים, הערכת עבודה ותוכנית הטמעה עם תחומי אחריות ונקודות בקרה. תארו את המשימה ושלחו את מה שכבר קיים — נחזור עם הערכה ותוכנית עבודה.