הסבר על שאילתות בזמן אמת בהיקף גדול
במאמר הזה מוסבר איך להרחיב את האפליקציה ללא שרתים כך שתתמוך ביותר מאלפי פעולות בשנייה או במאות אלפי משתמשים בו-זמנית. המסמך הזה כולל נושאים מתקדמים שיעזרו לכם להבין את המערכת לעומק. אם אתם רק מתחילים להשתמש ב-Firestore, כדאי לעיין במדריך למתחילים.
Firestore וערכות Firebase SDK לנייד ולאינטרנט מספקים מודל עוצמתי לפיתוח אפליקציות ללא שרת, שבו קוד בצד הלקוח ניגש ישירות למסד הנתונים. ערכות ה-SDK מאפשרות ללקוחות להאזין לעדכונים של הנתונים בזמן אמת. אתם יכולים להשתמש בעדכונים בזמן אמת כדי ליצור אפליקציות רספונסיביות שלא דורשות תשתית שרתים. קל מאוד להפעיל משהו, אבל כדאי להבין את האילוצים במערכות שמרכיבות את Firestore, כדי שהאפליקציה ללא שרת תהיה ניתנת להרחבה ותפעל בצורה טובה כשתנועת הגולשים תגדל.
בקטעים הבאים מפורטים טיפים להרחבת השימוש באפליקציה.
בחירת מיקום מסד נתונים שקרוב למשתמשים
התרשים הבא מדגים את הארכיטקטורה של אפליקציה בזמן אמת:
כשמתבצעת באפליקציה שפועלת במכשיר של משתמש (נייד או אינטרנט) יצירת חיבור ל-Firestore, החיבור מנותב לשרת קצה קדמי של Firestore באותו אזור שבו נמצאת מסד הנתונים. לדוגמה, אם מסד הנתונים נמצא ב-us-east1, החיבור מנותב גם לשרת קצה קדמי של Firestore שנמצא גם הוא ב-us-east1. החיבורים האלה הם ארוכי טווח ונשארים פתוחים עד שהאפליקציה סוגרת אותם באופן מפורש. הקצה הקדמי קורא נתונים ממערכות האחסון הבסיסיות של Firestore.
המרחק בין המיקום הפיזי של המשתמש לבין המיקום של מסד הנתונים של Firestore משפיע על זמן האחזור שהמשתמש חווה. לדוגמה, משתמש בהודו שהאפליקציה שלו מתקשרת עם מסד נתונים באזור Google Cloud בצפון אמריקה עשוי לחוות את השימוש באפליקציה כאיטי יותר, ופחות חלק מאשר אם מסד הנתונים היה ממוקם קרוב יותר, למשל בהודו או בחלק אחר של אסיה.
תכנון לאמינות
הנושאים הבאים משפרים את המהימנות של האפליקציה או מושפעים ממנה:
הפעלת מצב אופליין
ערכות ה-SDK של Firebase מספקות שמירה של נתונים במצב אופליין. אם האפליקציה במכשיר של המשתמש לא יכולה להתחבר ל-Firestore, המשתמש יכול להמשיך להשתמש באפליקציה באמצעות נתונים שנשמרו במטמון באופן מקומי. כך מובטחת גישה לנתונים גם אם החיבור לאינטרנט לא יציב או אם המשתמשים מאבדים את הגישה לאינטרנט למשך כמה שעות או ימים. לפרטים נוספים על מצב אופליין, אפשר לעיין במאמר בנושא הפעלת נתונים במצב אופליין.
הסבר על ניסיונות חוזרים אוטומטיים
ערכות ה-SDK של Firebase מטפלות בניסיון חוזר של פעולות ובחידוש של חיבורים שנפסקו. כך אפשר לעקוף שגיאות זמניות שנגרמות בגלל הפעלה מחדש של שרתים או בעיות ברשת בין הלקוח לבין מסד הנתונים.
בחירה בין מיקומים אזוריים לבין מיקומים בכמה אזורים
יש כמה שיקולים שצריך לקחת בחשבון כשבוחרים בין מיקומים אזוריים לבין מיקומים מרובי-אזורים. ההבדל העיקרי הוא באופן השכפול של הנתונים. זה משפיע על ערבויות הזמינות של האפליקציה. מופע מרובה-אזורים מספק אמינות גבוהה יותר בהצגת התוכן ומגדיל את העמידות של הנתונים, אבל החיסרון הוא העלות.
הסבר על מערכת השאילתות בזמן אמת
שאילתות בזמן אמת, שנקראות גם מאזינים ל-snapshot, מאפשרות לאפליקציה להאזין לשינויים במסד הנתונים ולקבל התראות עם השהיה נמוכה ברגע שהנתונים משתנים. אפליקציה יכולה לקבל את אותה תוצאה על ידי שליחת שאילתות למסד הנתונים באופן תקופתי כדי לקבל עדכונים, אבל בדרך כלל זה לוקח יותר זמן, עולה יותר כסף ודורש יותר קוד. דוגמאות להגדרת שאילתות בזמן אמת ולשימוש בהן מופיעות במאמר קבלת עדכונים בזמן אמת. בקטעים הבאים מפורט איך פועלים מאזינים לתמונת מצב, ומתוארות כמה מהשיטות המומלצות להרחבת היקף השאילתות בזמן אמת תוך שמירה על הביצועים.
נניח שיש שני משתמשים שמתחברים ל-Firestore דרך אפליקציית הודעות שנבנתה באמצעות אחת מערכות ה-SDK לנייד.
לקוח א' כותב למסד הנתונים כדי להוסיף ולעדכן מסמכים באוסף שנקרא chatroom:
collection chatroom:
document message1:
from: 'Sparky'
message: 'Welcome to Firestore!'
document message2:
from: 'Santa'
message: 'Presents are coming'
לקוח ב' מאזין לעדכונים באותו אוסף באמצעות מאזין לתמונת מצב. לקוח ב' מקבל התראה מיידית בכל פעם שמישהו יוצר הודעה חדשה. התרשים הבא מציג את הארכיטקטורה שמאחורי מאזין לתמונת מצב:
רצף האירועים הבא מתרחש כשלקוח ב' מחבר מאזין של תמונת מצב למסד הנתונים:
- לקוח ב' פותח חיבור ל-Firestore ורושם מאזין על ידי ביצוע קריאה ל-
onSnapshot(collection("chatroom"))דרך Firebase SDK. המאזין הזה יכול להישאר פעיל במשך שעות. - הקצה הקדמי של Firestore שולח שאילתות למערכת האחסון הבסיסית כדי לאתחל את קבוצת הנתונים. הוא טוען את כל קבוצת התוצאות של מסמכים תואמים. אנחנו קוראים לזה שאילתת בדיקה. לאחר מכן המערכת מעריכה את כללי האבטחה של Firebase במסד הנתונים כדי לוודא שלמשתמש יש גישה לנתונים האלה. אם המשתמש מורשה, מסד הנתונים מחזיר את הנתונים למשתמש.
- השאילתה של לקוח ב' עוברת למצב האזנה. המאזין נרשם לטיפול במינוי וממתין לעדכונים בנתונים.
- לקוח א' שולח עכשיו פעולת כתיבה כדי לשנות מסמך.
- מסד הנתונים מבצע את השינוי במסמך במערכת האחסון שלו.
- מבחינת טרנזקציות, המערכת מבצעת את אותו עדכון ביומן שינויים פנימי. יומן השינויים קובע סדר קפדני של השינויים בזמן שהם מתרחשים.
- יומן השינויים מעביר את הנתונים המעודכנים למאגר של מטפלי מינויים.
- התאמת שאילתות הפוכות מופעלת כדי לבדוק אם המסמך המעודכן תואם לאחד מהמאזינים ל-snapshot שרשומים כרגע. בדוגמה הזו, המסמך תואם למאזין ל-snapshot של לקוח ב'. כמו שהשם מרמז, אפשר לחשוב על התאמת שאילתות הפוכות כעל שאילתת מסד נתונים רגילה, אבל הפוכה. במקום לחפש במסמכים כדי למצוא את אלה שתואמים לשאילתה, המערכת מחפשת ביעילות בשאילתות כדי למצוא את אלה שתואמות למסמך נכנס. כשנמצאת התאמה, המערכת מעבירה את המסמך הרלוונטי למאזינים ל-snapshot. לאחר מכן, המערכת מעריכה את כללי האבטחה של Firebase במסד הנתונים כדי לוודא שרק משתמשים מורשים מקבלים את הנתונים.
- המערכת מעבירה את עדכון המסמך ל-SDK במכשיר של לקוח ב', ופונקציית הקריאה החוזרת
onSnapshotמופעלת. אם מופעלת התמדה מקומית, אפליקציית ה-SDK מחילה את העדכון גם על המטמון המקומי.
חלק חשוב מהיכולת של Firestore להתרחב תלוי ב-fan-out של יומן השינויים למטפלים במינויים ולשרתי הקצה הקדמי. ה-fan-out מאפשר להפיץ שינוי נתונים יחיד ביעילות כדי להציג מיליוני שאילתות בזמן אמת ומשתמשים מחוברים. כדי להשיג זמינות וגמישות גבוהות, מערכת Firestore מפעילה הרבה עותקים של כל הרכיבים האלה בכמה אזורים (או בכמה אזורים במקרה של פריסה בכמה אזורים).
חשוב לציין שכל פעולות הקריאה שמונפקות מ-SDK לנייד ומ-SDK לאינטרנט פועלות לפי המודל שלמעלה. הם מבצעים שאילתת סקר ואז עוברים למצב האזנה כדי לשמור על עקביות. ההגבלה הזו חלה גם על מאזינים בזמן אמת, על קריאות לאחזור מסמך ועל שאילתות חד-פעמיות. אפשר לחשוב על שליפות של מסמך יחיד ועל שאילתות מדוגמה אחת כמאזינים לתמונת מצב לזמן קצר, עם מגבלות דומות לגבי הביצועים.
יישום שיטות מומלצות להרחבת שאילתות בזמן אמת
כדי לעצב שאילתות בזמן אמת שניתנות להרחבה, כדאי לפעול לפי השיטות המומלצות הבאות.
הסבר על נפח גבוה של תנועת כתיבה במערכת
בקטע הזה מוסבר איך המערכת מגיבה למספר הולך וגדל של בקשות כתיבה.
יומני השינויים של Firestore שמפעילים את השאילתות בזמן אמת מתרחבים באופן אוטומטי ככל שתנועת הכתיבה גדלה. ככל שקצב הכתיבה למסד נתונים גדל מעבר למה ששרת יחיד יכול לטפל בו, יומן השינויים מתפצל בין כמה שרתים, ועיבוד השאילתות מתחיל לצרוך נתונים מכמה מטפלים במנויים במקום מאחד. מנקודת המבט של הלקוח ושל ה-SDK, הכול שקוף ולא נדרשת פעולה מהאפליקציה כשמתרחשים פיצולים. בתרשים הבא מוצג איך השאילתות בזמן אמת מתרחבות:
התאמה אוטומטית לעומס מאפשרת להגדיל את תנועת הכתיבה ללא הגבלות, אבל ככל שהתנועה גדלה, יכול להיות שיעבור זמן עד שהמערכת תגיב. כדי להימנע מיצירת נקודה חמה לכתיבה, מומלץ לפעול לפי ההמלצות של כלל 5-5-5. Key Visualizer הוא כלי שימושי לניתוח נקודות חמות של כתיבה.
להרבה אפליקציות יש צמיחה אורגנית צפויה, שאפשר להתמודד איתה ב-Firestore בלי לנקוט אמצעי זהירות. עם זאת, עומסי עבודה של אצווה, כמו ייבוא של מערך נתונים גדול, יכולים להגדיל את מספר הפעולות של כתיבה מהר מדי. כשמעצבים את האפליקציה, חשוב לדעת מאיפה מגיע נפח התנועה של פעולות הכתיבה.
הסבר על האינטראקציה בין פעולות כתיבה וקריאה
אפשר לחשוב על מערכת השאילתות בזמן אמת כעל צינור שמקשר בין פעולות כתיבה לבין קוראים. בכל פעם שיוצרים, מעדכנים או מוחקים מסמך, השינוי מועבר ממערכת האחסון למאזינים שרשומים כרגע. מבנה יומן השינויים של Firestore מבטיח עקביות חזקה, כלומר האפליקציה שלכם לעולם לא תקבל התראות על עדכונים שהסדר שלהם לא תואם לסדר שבו מסד הנתונים ביצע את שינויי הנתונים. הגישה הזו מפשטת את פיתוח האפליקציות כי היא מסירה מקרים חריגים שקשורים לעקביות הנתונים.
צינור עיבוד הנתונים המחובר הזה אומר שפעולת כתיבה שגורמת לנקודות חמות או למאבק על נעילה יכולה להשפיע לרעה על פעולות קריאה. כשפעולות כתיבה נכשלות או מוגבלות, יכול להיות שפעולת קריאה תיתקע בהמתנה לנתונים עקביים מיומן השינויים. אם זה קורה באפליקציה שלכם, יכול להיות שתראו גם פעולות כתיבה איטיות וגם זמני תגובה איטיים לשאילתות. כדי להימנע מהבעיה הזו, חשוב להימנע מנקודות חמות.
צריך לשמור על מסמכים קטנים ועל פעולות כתיבה קטנות
כשמפתחים אפליקציות עם מאזינים ל-snapshot, בדרך כלל רוצים שהמשתמשים יקבלו מידע על שינויים בנתונים במהירות. כדי להשיג את זה, כדאי לשמור על גודל קטן. המערכת יכולה להעביר מסמכים קטנים עם עשרות שדות דרך המערכת במהירות רבה. עיבוד של מסמכים גדולים עם מאות שדות ונתונים גדולים נמשך זמן רב יותר.
באופן דומה, מומלץ להשתמש בפעולות קצרות ומהירות של שליחה וכתיבה כדי לשמור על זמן אחזור נמוך. אפשר להשתמש בקבוצות גדולות כדי להגדיל את קצב העברת הנתונים מנקודת המבט של הכותב, אבל זה עלול להגדיל את זמן ההתראה למאזיני תמונת המצב. לרוב, זה לא אינטואיטיבי בהשוואה לשימוש במערכות מסדי נתונים אחרות, שבהן אפשר להשתמש באצווה כדי לשפר את הביצועים.
שימוש ברכיבי listener יעילים
ככל ששיעורי הכתיבה במסד הנתונים עולים, Firestore מפצל את עיבוד הנתונים בין שרתים רבים. אלגוריתם ה-sharding של Firestore מנסה למקם נתונים מאותה קולקציה או מאותה קבוצת קולקציות באותו שרת של יומן השינויים. המערכת מנסה למקסם את קצב העברת הנתונים האפשרי תוך שמירה על מספר השרתים שמעורבים בעיבוד של שאילתה נמוך ככל האפשר.
עם זאת, דפוסים מסוימים עדיין עלולים להוביל להתנהגות לא אופטימלית של מאזינים ל-snapshot. לדוגמה, אם האפליקציה מאחסנת את רוב הנתונים שלה באוסף גדול אחד, יכול להיות שהמאזין יצטרך להתחבר לשרתים רבים כדי לקבל את כל הנתונים שהוא צריך. זה נכון גם אם מפעילים מסנן שאילתות. התחברות לשרתים רבים מגדילה את הסיכון לתגובות איטיות יותר.
כדי להימנע מתשובות איטיות כאלה, צריך לתכנן את הסכימה והאפליקציה כך שהמערכת תוכל להציג למאזינים תוכן בלי לעבור בין הרבה שרתים שונים. יכול להיות שהכי טוב יהיה לפצל את הנתונים לקבוצות קטנות יותר עם שיעורי כתיבה נמוכים יותר.
זה דומה למחשבה על שאילתות ביצועים במסד נתונים רלציוני שדורשות סריקות מלאות של הטבלה. במסד נתונים רלציוני, שאילתה שדורשת סריקה מלאה של הטבלה שקולה למאזין של תמונת מצב שעוקב אחרי אוסף עם שיעור תחלופה גבוה. יכול להיות שהביצוע יהיה איטי יותר בהשוואה לשאילתה שהמסד יכול להציג באמצעות אינדקס ספציפי יותר. שאילתה עם אינדקס ספציפי יותר דומה למאזין של תמונת מצב שעוקב אחרי מסמך יחיד או אוסף שמשתנים בתדירות נמוכה יותר. כדאי לטעון את האפליקציה ולבדוק אותה כדי להבין בצורה הטובה ביותר את ההתנהגות ואת הצורך של תרחיש השימוש שלכם.
שמירה על מהירות של שאילתות סקר
חלק חשוב נוסף בשאילתות רספונסיביות בזמן אמת הוא לוודא ששאילתת הסקר לאתחול הנתונים מהירה ויעילה. בפעם הראשונה שמאזין חדש של תמונת מצב מתחבר, המאזין צריך לטעון את כל קבוצת התוצאות ולשלוח אותה למכשיר של המשתמש. שאילתות איטיות מפחיתות את הרספונסיביות של האפליקציה. זה כולל, למשל, שאילתות שמנסות לקרוא הרבה מסמכים או שאילתות שלא משתמשות באינדקסים המתאימים.
יכול להיות שבנסיבות מסוימות, מאזין יעבור ממצב האזנה למצב בדיקה. זה קורה באופן אוטומטי ושקוף לערכות ה-SDK ולאפליקציה שלכם. התנאים הבאים עשויים להפעיל מצב בדיקה:
- המערכת מאזנת מחדש את יומן השינויים בגלל שינויים בעומס.
- נקודות חמות גורמות לכתיבה למסד הנתונים להיכשל או להתעכב.
- הפעלות מחדש זמניות של שרתים משפיעות על מאזינים באופן זמני.
אם שאילתות ה-Polling שלכם מהירות מספיק, מצב ה-Polling הופך לשקוף למשתמשי האפליקציה.
עדיפות להגדרות listener לטווח ארוך
פתיחה של מאזינים והשארתם פעילים למשך זמן רב ככל האפשר היא לרוב הדרך הכי חסכונית ליצור אפליקציה שמשתמשת ב-Firestore. כשמשתמשים ב-Firestore, החיוב הוא על המסמכים שמוחזרים לאפליקציה ולא על שמירת חיבור פתוח. מאזין ל-snapshot לטווח ארוך קורא רק את הנתונים שהוא צריך כדי להציג את השאילתה לאורך כל משך החיים שלו. זה כולל פעולת תשאול ראשונית ואחריה התראות כשהנתונים משתנים בפועל. לעומת זאת, שאילתות חד-פעמיות קוראות מחדש נתונים שאולי לא השתנו מאז שהאפליקציה הרצה את השאילתה בפעם האחרונה.
במקרים שבהם האפליקציה צריכה לצרוך נתונים בקצב גבוה, יכול להיות שמאזינים לתמונת מצב לא יתאימו. לדוגמה, אם בתרחיש השימוש שלכם נשלחים הרבה מסמכים בשנייה דרך חיבור למשך תקופה ממושכת, יכול להיות שעדיף להשתמש בשאילתות חד-פעמיות שמופעלות בתדירות נמוכה יותר.