להבין שאילתות בזמן אמת בקנה מידה נרחב

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

Cloud Firestore וערכות ה-SDK לנייד ולאינטרנט של Firebase מספקות מודל חזק לפיתוח אפליקציות ללא שרת (serverless), שבהן הקוד בצד הלקוח ניגש ישירות למסד הנתונים. ערכות ה-SDK מאפשרות ללקוחות להאזין לעדכונים בנתונים בזמן אמת. אפשר להשתמש בעדכונים בזמן אמת כדי ליצור אפליקציות רספונסיביות שלא דורשות תשתית שרת. קל מאוד להפעיל אפליקציה ללא שרת, אבל כדאי להבין את המגבלות של המערכות שמרכיבות את Cloud Firestore כדי שהאפליקציה תתאים את עצמה לעומס ותמשיך לפעול בצורה טובה כשהתנועה תגבר.

בקטעים הבאים מפורטות המלצות להתאמת האפליקציה לעומס.

בחירת מיקום של מסד נתונים קרוב למשתמשים

התרשים הבא מדגים את הארכיטקטורה של אפליקציה בזמן אמת:

דוגמה לארכיטקטורה של אפליקציה בזמן אמת

כשאפליקציה שפועלת במכשיר של משתמש (נייד או אינטרנט) יוצרת חיבור ל-Cloud Firestore, החיבור מנותב לשרת חזית של Cloud Firestore באותו אזור שבו ממוקם מסד הנתונים. לדוגמה, אם מסד הנתונים נמצא ב-us-east1, החיבור יגיע גם לקצה קדמי של Cloud Firestore שנמצא גם ב-us-east1. החיבורים האלה הם לטווח ארוך ונשארים פתוחים עד שהאפליקציה סוגרת אותם באופן מפורש. הקצה הקדמי קורא נתונים ממערכות האחסון הבסיסיות של Cloud Firestore.

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

תכנון למען אמינות

הנושאים הבאים משפרים את האמינות של האפליקציה או משפיעים עליה:

הפעלת מצב אופליין

ערכות ה-SDK של Firebase מספקות שמירת נתונים במצב אופליין. אם האפליקציה במכשיר של המשתמש לא יכולה להתחבר אל Cloud Firestore, אפשר להמשיך להשתמש בה על ידי עבודה עם נתונים שנשמרו במטמון באופן מקומי. כך תוכלו להבטיח גישה לנתונים גם אם המשתמשים מדווחים על חיבורי אינטרנט לא יציבים או על אובדן גישה מוחלט למשך כמה שעות או ימים. מידע נוסף על מצב אופליין זמין במאמר הפעלת נתונים אופליין.

הסבר על ניסיונות חוזרים אוטומטיים

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

בחירה בין מיקומים אזוריים למיקומים בכמה אזורים

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

הסבר על מערכת השאילתות בזמן אמת

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

נניח שיש שני משתמשים שמתחברים ל-Cloud Firestore דרך אפליקציית הודעות שנוצרה באמצעות אחת מערכות ה-SDK לנייד.

לקוח א' כותב למסד הנתונים כדי להוסיף ולעדכן מסמכים באוסף שנקרא chatroom:

collection chatroom:
    document message1:
      from: 'Sparky'
      message: 'Welcome to Cloud Firestore!'

    document message2:
      from: 'Santa'
      message: 'Presents are coming'

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

הארכיטקטורה של חיבור של מאזין לתמונות מצב

רצף האירועים הבא מתרחש כשלקוח ב' מחבר מאזין של קובץ snapshot למסד הנתונים:

  1. לקוח ב' פותח חיבור אל Cloud Firestore ומירשם מאזין על ידי ביצוע קריאה ל-onSnapshot(collection("chatroom")) דרך Firebase SDK. המאזין הזה יכול להישאר פעיל במשך שעות.
  2. חזית Cloud Firestore שולחת שאילתות למערכת האחסון הבסיסית כדי לאתחל את מערך הנתונים. הוא טוען את כל קבוצת התוצאות של המסמכים התואמים. אנחנו מכנים זאת שאילתה של סקרים. לאחר מכן המערכת מבצעת הערכה של כללי האבטחה של Firebase במסד הנתונים כדי לוודא שהמשתמש יכול לגשת לנתונים האלה. אם המשתמש מורשה, מסד הנתונים מחזיר את הנתונים למשתמש.
  3. לאחר מכן, השאילתה של לקוח ב' עוברת למצב הקשבה. המאזין מתעדכן אצל גורם טיפול במינויים וממתין לעדכונים בנתונים.
  4. לקוח א' שולח עכשיו פעולת כתיבה כדי לשנות מסמך.
  5. מסד הנתונים מבצע את השינויים במסמך במערכת האחסון שלו.
  6. מבחינה עסקית, המערכת מבצעת את אותו עדכון ביומן השינויים הפנימי. ביומן השינויים מופיע סדר קפדני של השינויים כפי שהם מתרחשים.
  7. ביומן השינויים מתבצעת חלוקה של הנתונים המעודכנים למאגר של מודולים לטיפול במינוי.
  8. מתבצעת הפעלה של מתאמת שאילתות הפוך כדי לבדוק אם המסמך המעודכן תואם למאזינים של קובצי snapshot שרשומים כרגע. בדוגמה הזו, המסמך תואם למאזין של קובץ ה-snapshot של לקוח ב'. כפי שרומז השם, אפשר להתייחס למתאמת השאילתות ההפוכות כשאילתה רגילה של מסד נתונים, אבל הפוך. במקום לחפש במסמכים כדי למצוא את אלה שתואמים לשאילתה, המערכת מחפשת ביעילות שאילתות שתואמות למסמך נכנס. כשהמערכת מוצאת התאמה, היא מעבירה את המסמך הרלוונטי למאזינים של קובצי snapshot. לאחר מכן, המערכת מעריכה את כללי האבטחה של Firebase של מסד הנתונים כדי לוודא שרק משתמשים מורשים מקבלים את הנתונים.
  9. המערכת מעבירה את עדכון המסמך ל-SDK במכשיר של לקוח ב', והקריאה החוזרת (callback) של onSnapshot מופעלת. אם התכונה 'שמירה במטמון מקומי' מופעלת, ה-SDK מחיל את העדכון גם במטמון המקומי.

חלק מרכזי ביכולת ההתאמה לעומס של Cloud Firestore תלוי בהתפצלות מ-changelog למטפלי המינויים ולשרתי הקצה הקדמי. היצירה של ענפים מאפשרת לשינוי נתונים יחיד להתפשט ביעילות כדי לשרת מיליוני שאילתות ומשתמשים מחוברים בזמן אמת. הפעלת עותקים מרובים של כל הרכיבים האלה במספר תחומים (או במספר אזורים במקרה של פריסה במספר אזורים) מאפשרת ל-Cloud Firestore לספק זמינות גבוהה ויכולת התאמה גבוהה.

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

שימוש בשיטות מומלצות להתאמה לעומס של שאילתות בזמן אמת

כדאי להשתמש בשיטות המומלצות הבאות כדי לתכנן שאילתות בזמן אמת שניתן להתאים לעומס.

הסבר על נפח גבוה של תנועת כתיבה במערכת

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

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

הארכיטקטורה של יצירת ענפים ביומן השינויים

התאמה לעומס (autoscaling) מאפשרת לכם להגדיל את נפח התנועה לכתיבה ללא הגבלות, אבל ככל שהתנועה גוברת, יכול להיות שיחלוף זמן מה עד שהמערכת תגיב. כדי להימנע מיצירת נקודה חמה לכתיבה, פועלים לפי ההמלצות של כלל 5-5-5. Key Visualizer הוא כלי שימושי לניתוח נקודות חמות בכתיבה.

לאפליקציות רבות יש צמיחה אורגנית צפויה, ו-Cloud Firestore יכולה להתאים את עצמה לכך ללא אמצעי זהירות. עם זאת, עומסי עבודה של קבוצות (batch), כמו ייבוא של מערך נתונים גדול, יכולים להגדיל את נפח הכתיבה מהר מדי. כשיוצרים אפליקציה, חשוב לדעת מאיפה מגיע תנועת הכתיבה.

הסבר על האינטראקציה בין פעולות הכתיבה לפעולות הקריאה

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

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

כדאי לשמור על מסמכים ועל פעולות כתיבה קטנים

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

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

שימוש ברכיבי listener יעילים

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

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

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

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

שאילתות סקרים מהירות

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

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

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

אם שאילתות הסקרים שלכם מהירות מספיק, מצב הסקרים הופך לשקוף למשתמשים באפליקציה.

העדפה של פונקציות listener לטווח ארוך

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

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

המאמרים הבאים