במאמר הזה מוסבר איך לתכנן את הארכיטקטורה של האפליקציות כדי להשיג ביצועים גבוהים ומהימנות. המסמך הזה כולל נושאים מתקדמים בנושא Cloud Firestore. אם אתם רק מתחילים להשתמש ב-Cloud Firestore, כדאי לעיין במקום זאת במדריך למתחילים.
Cloud Firestore הוא מסד נתונים גמיש וניתן להרחבה לפיתוח של מכשירים ניידים, אינטרנט ושרתים מ-Firebase ו-Google Cloud. קל מאוד להתחיל לעבוד עם Cloud Firestore ולכתוב אפליקציות עשירות ומתקדמות.
כדי לוודא שהאפליקציות ימשיכו לפעול בצורה טובה ככל שגודל מסד הנתונים והתנועה יגדלו, כדאי להבין את המנגנונים של פעולות קריאה וכתיבה בCloud Firestoreקצה העורפי. חשוב גם להבין את האינטראקציה של פעולות הקריאה והכתיבה עם שכבת האחסון ואת האילוצים הבסיסיים שעשויים להשפיע על הביצועים.
לפני שמתכננים את האפליקציה, כדאי לעיין בשיטות המומלצות שמפורטות בקטעים הבאים.
הסבר על הרכיבים ברמה הגבוהה
הדיאגרמה הבאה מציגה את הרכיבים ברמה גבוהה שמעורבים בבקשת API של Cloud Firestore.
Cloud Firestore SDK וספריות לקוח
Cloud Firestore תומך בערכות SDK ובספריות לקוח לפלטפורמות שונות. אפליקציה יכולה לבצע קריאות HTTP ו-RPC ישירות ל-Cloud Firestore API, אבל ספריות הלקוח מספקות שכבת הפשטה כדי לפשט את השימוש ב-API וליישם שיטות מומלצות. יכול להיות שהם יספקו גם תכונות נוספות כמו גישה אופליין, מטמונים וכו'.
ממשק קצה של Google (GFE)
זהו שירות תשתיתי שמשותף לכל שירותי הענן של Google. ממשק GFE מקבל בקשות נכנסות ומעביר אותן לשירות Google הרלוונטי (שירות Cloud Firestore בהקשר הזה). הוא גם מספק פונקציות חשובות אחרות, כולל הגנה מפני התקפות מניעת שירות (DoS).
שירות Cloud Firestore
שירות Cloud Firestore מבצע בדיקות של בקשת ה-API, כולל אימות, הרשאה, בדיקות מכסה וכללי אבטחה, וגם מנהל טרנזקציות. Cloud Firestore השירות הזה כולל לקוח אחסון שמקיים אינטראקציה עם שכבת האחסון לצורך קריאה וכתיבה של נתונים.
שכבת אחסון בנפח Cloud Firestore
שכבת האחסון של Cloud Firestore אחראית לאחסון הנתונים והמטא-נתונים, ולתכונות המשויכות של מסד הנתונים שסופקו על ידי Cloud Firestore. בקטעים הבאים מוסבר איך הנתונים מאורגנים בשכבת האחסון Cloud Firestore ואיך המערכת מתרחבת. הבנה של האופן שבו הנתונים מאורגנים יכולה לעזור לכם לתכנן מודל נתונים שניתן להרחבה, ולהבין טוב יותר את השיטות המומלצות ב-Cloud Firestore.
טווחים ופיצולים של מפתחות
Cloud Firestore הוא מסד נתונים מסוג NoSQL שמבוסס על מסמכים. הנתונים מאוחסנים במסמכים, שמסודרים בהיררכיות של אוספים. היררכיית האוסף ומזהה המסמך מתורגמים למפתח יחיד לכל מסמך. המסמכים מאוחסנים באופן לוגי ומסודרים לקסיקוגרפית לפי המפתח היחיד הזה. אנחנו משתמשים במונח 'טווח מפתחות' כדי להתייחס לטווח רציף של מפתחות לפי סדר מילוני.
בדרך כלל, מסד נתונים של Cloud Firestore גדול מדי מכדי להיכנס למכונה פיזית אחת. יש גם תרחישים שבהם עומס העבודה על הנתונים כבד מדי בשביל שמכונה אחת תוכל להתמודד איתו. כדי לטפל בעומסי עבודה גדולים, Cloud Firestore מחלקת את הנתונים לחלקים נפרדים שאפשר לאחסן ולהציג ממכונות מרובות או משרתי אחסון. החלוקה למחיצות מתבצעת בטבלאות של מסד הנתונים בבלוקים של טווחי מפתחות שנקראים פיצולים.
שכפול סינכרוני
חשוב לציין שהמסד נתונים תמיד משוכפל באופן אוטומטי וסינכרוני. לפילוגים של הנתונים יש רפליקות באזורים שונים, כדי שהם יישארו זמינים גם אם אזור מסוים לא נגיש. השכפול העקבי של העותקים השונים של הפיצול מנוהל על ידי אלגוריתם Paxos להשגת הסכמה. עותק אחד של כל פיצול נבחר לפעול כמנהיג Paxos, שאחראי לטיפול בפעולות כתיבה לפיצול הזה. השכפול הסינכרוני מאפשר לכם לקרוא תמיד את הגרסה העדכנית ביותר של הנתונים מ-Cloud Firestore.
התוצאה הכוללת היא מערכת ניתנת להרחבה עם זמינות גבוהה, שמספקת זמני אחזור נמוכים לקריאה ולכתיבה, ללא קשר לעומסי עבודה כבדים ובקנה מידה גדול מאוד.
פריסת נתונים
Cloud Firestore הוא מסד נתונים של מסמכים ללא סכימה. עם זאת, באופן פנימי, הנתונים מסודרים בעיקר בשתי טבלאות בסגנון של מסד נתונים יחסי בשכבת האחסון, באופן הבא:
- טבלת Documents: המסמכים מאוחסנים בטבלה הזו.
- טבלת האינדקסים: בטבלה הזו מאוחסנים רשומות אינדקס שמאפשרות לקבל תוצאות בצורה יעילה וממוינות לפי ערך האינדקס.
בתרשים הבא אפשר לראות איך יכולות להיראות הטבלאות במסד נתונים Cloud Firestore עם הפיצולים. הפיצולים משוכפלים בשלושה אזורים שונים, ולכל פיצול מוקצה מוביל Paxos.
אזור יחיד לעומת מספר אזורים
כשיוצרים מסד נתונים, צריך לבחור אזור או אזור גיאוגרפי נרחב יותר שכולל מספר אזורים.
מיקום אזורי יחיד הוא מיקום גיאוגרפי ספציפי, כמו us-west1. כמו שהוסבר קודם, לנתונים של מסד נתונים Cloud Firestore יש רפליקות באזורים שונים בתוך האזור שנבחר.
מיקום במספר אזורים מורכב מקבוצה מוגדרת של אזורים שבהם מאוחסנות רפליקות של מסד הנתונים. בפריסה של Cloud Firestore במספר אזורים, שניים מהאזורים כוללים עותקים מלאים של כל הנתונים במסד הנתונים. באזור שלישי יש עותק משוכפל של עד שלא מכיל את כל הנתונים, אבל משתתף בשכפול. על ידי שכפול הנתונים בין כמה אזורים, הנתונים זמינים לכתיבה ולקריאה גם במקרה של אובדן של אזור שלם.
מידע נוסף על המיקומים של אזור זמין במאמר Cloud Firestore מיקומים.
הסבר על תוקף כתיבה ב-Cloud Firestore
Cloud Firestore לקוח יכול לכתוב נתונים על ידי יצירה, עדכון או מחיקה של מסמך יחיד. כתיבה למסמך יחיד מחייבת עדכון אטומי של המסמך ושל רשומות האינדקס המשויכות בשכבת האחסון. Cloud Firestore תומך גם בפעולות אטומיות שכוללות כמה קריאות או כתיבות למסמך אחד או יותר.
לכל סוגי הכתיבה, Cloud Firestore מספק את מאפייני ה-ACID (אטומיות, עקביות, בידוד ועמידות) של מסדי נתונים יחסיים. Cloud Firestore מספק גם serializability, כלומר כל העסקאות מופיעות כאילו בוצעו בסדר סדרתי.
שלבים כלליים בעסקת כתיבה
כשלקוח Cloud Firestore מבצע פעולת כתיבה או מאשר עסקה באמצעות אחת מהשיטות שצוינו קודם, הפעולה הזו מבוצעת באופן פנימי כעסקה של קריאה וכתיבה במסד נתונים בשכבת האחסון. הטרנזקציה מאפשרת ל-Cloud Firestore לספק את מאפייני ה-ACID שצוינו קודם.
בשלב הראשון של העסקה, Cloud Firestore קורא את המסמך הקיים וקובע את השינויים שיבוצעו בנתונים בטבלת המסמכים.
הפעולה הזו כוללת גם ביצוע עדכונים נדרשים בטבלת האינדקסים, באופן הבא:
- לשדות שמוסיפים למסמכים צריך להוסיף הוספות תואמות בטבלת האינדקסים.
- כשמסירים שדות מהמסמכים, צריך להסיר אותם גם מטבלת האינדקסים.
- בשדות שמשתנים במסמכים, צריך גם מחיקות (של ערכים ישנים) וגם הוספות (של ערכים חדשים) בטבלת האינדקסים.
כדי לחשב את המוטציות שצוינו קודם, Cloud Firestore קורא את הגדרת האינדוקס של הפרויקט. הגדרת האינדקס שומרת מידע על האינדקסים של פרויקט. Cloud Firestore משתמש בשני סוגים של אינדקסים: אינדקסים של שדה יחיד ואינדקסים מורכבים. למידע מפורט על האינדקסים שנוצרו ב-Cloud Firestore, אפשר לעיין במאמר סוגי אינדקסים ב-Cloud Firestore.
אחרי שהמוטציות מחושבות, Cloud Firestore אוסף אותן בתוך טרנזקציה ואז מבצע commit.
הסבר על עסקת כתיבה בשכבת האחסון
כמו שהסברנו קודם, פעולת כתיבה ב-Cloud Firestore כוללת טרנזקציה של קריאה וכתיבה בשכבת האחסון. בהתאם לפריסת הנתונים, פעולת כתיבה עשויה לכלול פיצול אחד או יותר, כפי שמוצג בפריסת הנתונים.
בתרשים הבא, מסד הנתונים Cloud Firestore מחולק לשמונה חלקים (מסומנים ב-1 עד 8) שמתארחים בשלושה שרתי אחסון שונים באותו אזור, וכל חלק משוכפל בשלושה אזורים שונים(או יותר). לכל פיצול יש מוביל Paxos, שיכול להיות באזור אחר עבור פיצולים שונים.
פיצול מסד נתונים ב-Cloud Firestore">
נניח שיש מסד נתונים Cloud Firestore עם אוסף Restaurants
באופן הבא:
לקוח Cloud Firestore מבקש לבצע את השינוי הבא במסמך באוסף Restaurant
על ידי עדכון הערך של השדה priceCategory
.
השלבים הבאים מתארים מה קורה כחלק מהכתיבה:
- יוצרים טרנזקציה עם הרשאת קריאה וכתיבה.
- קריאה של מסמך
restaurant1
באוסףRestaurants
מהטבלה Documents משכבת האחסון. - קוראים את האינדקסים של המסמך מהטבלה Indexes.
- חישוב השינויים שצריך לבצע בנתונים. במקרה הזה, יש חמש מוטציות:
- M1: מעדכנים את השורה של
restaurant1
בטבלה Documents כך שתשקף את השינוי בערך של השדהpriceCategory
. - M2 ו-M3: מוחקים את השורות של הערך הישן של
priceCategory
בטבלה Indexes עבור אינדקסים בסדר יורד וסדר עולה. - M4 ו-M5: מוסיפים את השורות של הערך החדש של
priceCategory
בטבלה Indexes לאינדקסים בסדר יורד ובסדר עולה.
- M1: מעדכנים את השורה של
- מאשרים את המוטציות האלה.
לקוח האחסון בשירות Cloud Firestore מחפש את הפיצולים שבבעלותם המפתחות של השורות שרוצים לשנות. נניח שפיצול 3 מציג את M1, ופיצול 6 מציג את M2-M5. מדובר בעסקה מבוזרת, שבה כל הפיצולים האלה הם משתתפים. הפיצולים של המשתתפים עשויים לכלול גם פיצולים אחרים שמהם נתונים נקראו קודם כחלק מעסקת הקריאה והכתיבה.
בשלבים הבאים מתואר מה קורה כחלק מההתחייבות:
- לקוח האחסון מנפיק אישור. הקומִיט מכיל את המוטציות M1-M5.
- המשתתפים בעסקה הזו הם 3 ו-6. אחד מהמשתתפים נבחר כמתאם, למשל Split 3. תפקיד המתאם הוא לוודא שהעסקה מתבצעת או מבוטלת באופן אטומי אצל כל המשתתפים.
- העותקים המובילים של הפיצולים האלה אחראים לעבודה שמבצעים המשתתפים והמתאמים.
- כל משתתף וכל מתאם מריצים אלגוריתם Paxos עם העותקים המתאימים שלהם.
- המוביל מריץ אלגוריתם Paxos עם העותקים. הקונצנזוס מושג אם רוב העותקים משיבים למנהיג בתגובה
ok to commit
. - כל משתתף מודיע לרכז שהוא מוכן (השלב הראשון מתוך שני שלבים של אישור פעולה). אם אחד מהמשתתפים לא יכול לאשר את העסקה, העסקה כולה
aborts
.
- המוביל מריץ אלגוריתם Paxos עם העותקים. הקונצנזוס מושג אם רוב העותקים משיבים למנהיג בתגובה
- אחרי שהמתאם יודע שכל המשתתפים, כולל הוא עצמו, מוכנים, הוא מעביר את תוצאת העסקה
accept
לכל המשתתפים (השלב השני של אישור דו-שלבי). בשלב הזה, כל משתתף מתעד את החלטת האישור באחסון יציב והעסקה מאושרת. - המתאם משיב ללקוח האחסון ב-Cloud Firestore שהעסקה בוצעה. במקביל, הרכיב המתאם וכל המשתתפים מחילים את השינויים על הנתונים.
כשמסד הנתונים Cloud Firestore קטן, יכול להיות שפיצול יחיד יכיל את כל המפתחות במוטציות M1-M5. במקרה כזה, יש רק משתתף אחד בעסקה, ולא נדרש אישור דו-שלבי כמו שצוין קודם, ולכן פעולות הכתיבה מהירות יותר.
כתיבה במספר אזורים
בפריסה במספר אזורים, פיזור העותקים המשוכפלים בין האזורים מגדיל את הזמינות, אבל יש לכך השפעה על הביצועים. התקשורת בין העותקים באזורים שונים אורכת יותר זמן. לכן, זמן האחזור הבסיסי לפעולות Cloud Firestore גבוה מעט יותר בהשוואה לפריסות באזור יחיד.
אנחנו מגדירים את העותקים המשוכפלים כך שהשליטה בחלוקות תמיד תישאר באזור הראשי. האזור הראשי הוא האזור שממנו מגיעה התנועה לשרת Cloud Firestore. ההחלטה הזו של ההנהלה מקצרת את זמן האחזור הלוך ושוב בתקשורת בין לקוח האחסון ב-Cloud Firestore לבין העותק הראשי (או הרכיב המתאם לעסקאות מרובות פיצולים).
כל פעולת כתיבה ב-Cloud Firestore כוללת גם אינטראקציה עם מנוע בזמן אמת ב-Cloud Firestore. מידע נוסף על שאילתות בזמן אמת זמין במאמר הסבר על שאילתות בזמן אמת בהיקף גדול.
הסבר על משך הזמן של קריאה ב-Cloud Firestore
בקטע הזה נסביר על קריאות עצמאיות שלא מתבצעות בזמן אמת ב-Cloud Firestore. באופן פנימי, שרת Cloud Firestore מטפל ברוב השאילתות האלה בשני שלבים עיקריים:
- סריקה של טווח יחיד בטבלה Indexes
- חיפושים של נקודות בטבלת מסמכים על סמך תוצאת הסריקה הקודמת
קריאות הנתונים משכבת האחסון מתבצעות באופן פנימי באמצעות טרנזקציה במסד נתונים, כדי להבטיח קריאות עקביות. אבל בניגוד לעסקאות שמשמשות לכתיבה, העסקאות האלה לא נועלות את הנתונים. במקום זאת, הן פועלות על ידי בחירת חותמת זמן, ואז ביצוע כל פעולות הקריאה בחותמת הזמן הזו. מכיוון שהם לא מקבלים נעילות, הם לא חוסמים עסקאות קריאה-כתיבה בו-זמניות. כדי לבצע את העסקה הזו, לקוח האחסון ב-Cloud Firestore מציין חותמת זמן של גבול, שמציינת לשכבת האחסון איך לבחור חותמת זמן של קריאה. סוג חותמת הזמן שמוגדרת על ידי לקוח האחסון ב-Cloud Firestore נקבע לפי אפשרויות הקריאה של בקשת הקריאה.
הסבר על עסקת קריאה בשכבת האחסון
בקטע הזה מתוארים סוגי הקריאות ואופן העיבוד שלהן בשכבת האחסון ב-Cloud Firestore.
קריאה חזקה
כברירת מחדל, פעולות Cloud Firestore קריאה הן עקביות חזקות. העקביות החזקה הזו אומרת שקריאה של Cloud Firestore מחזירה את הגרסה האחרונה של הנתונים שמשקפת את כל הכתיבות שאושרו עד תחילת הקריאה.
קריאה של מסך מפוצל יחיד
לקוח האחסון ב-Cloud Firestore מחפש את הפיצולים שכוללים את המפתחות של השורות שצריך לקרוא. נניח שהיא צריכה לקרוא מ-Split 3 מהקטע הקודם. הלקוח שולח את בקשת הקריאה לרפליקה הקרובה ביותר כדי לצמצם את זמן האחזור של הלוך ושוב.
בשלב הזה, יכולים לקרות המקרים הבאים בהתאם לשכפול שנבחר:
- בקשת קריאה מועברת לרפליקה ראשית (אזור א').
- מכיוון שהמוביל תמיד מעודכן, הקריאה יכולה להתבצע ישירות.
- בקשת קריאה מועברת לרפליקה שאינה רפליקת הלידר (לדוגמה, אזור ב')
- יכול להיות ש-Split 3 ידע מהמצב הפנימי שלו שיש לו מספיק מידע כדי להציג את הקריאה, והוא יעשה זאת.
- הפיצול 3 לא בטוח אם הוא ראה את הנתונים האחרונים. הוא שולח הודעה למוביל כדי לבקש את חותמת הזמן של העסקה האחרונה שהוא צריך להחיל כדי להציג את הקריאה. אחרי שהעסקה הזו תיושם, אפשר יהיה להמשיך בקריאה.
Cloud Firestore ומחזירה את התגובה ללקוח שלה.
קריאה עם פיצול מסך
במצב שבו צריך לבצע קריאות מכמה פיצולים, אותו מנגנון פועל בכל הפיצולים. אחרי שהנתונים מוחזרים מכל הפיצולים, לקוח האחסון ב-Cloud Firestore משלב את התוצאות. Cloud Firestore משיבה ללקוח עם הנתונים האלה.
מומלץ לצמצם את קבוצות התוצאות של השאילתות, במידת האפשר.קריאות בעבר
הקראות חזקות הן מצב ברירת המחדל ב-Cloud Firestore. עם זאת, יש לכך מחיר: השהיה גבוהה יותר, כי יכול להיות שיהיה צורך בתקשורת עם המנהיג. בדרך כלל, לאפליקציית Cloud Firestore לא נדרשת קריאה של הגרסה העדכנית ביותר של הנתונים, והפונקציונליות פועלת היטב עם נתונים שהם בני כמה שניות.
במקרה כזה, הלקוח יכול לבחור לקבל קריאות לא עדכניות באמצעות read_time
אפשרויות הקריאה. במקרה הזה, פעולות הקריאה מתבצעות כשהנתונים היו ב-read_time
, והסבירות גבוהה שהעותק המשוכפל הקרוב ביותר כבר אימת שיש בו נתונים ב-read_time
שצוין.
כדי ליהנות מביצועים טובים יותר באופן משמעותי, מומלץ להגדיר ערך של 15 שניות. גם בקריאות ישנות, השורות שמתקבלות עקביות זו עם זו.
הימנעות מנקודות חמות
הפיצולים ב-Cloud Firestore מפורקים אוטומטית לחלקים קטנים יותר כדי לחלק את העבודה של הצגת התנועה ליותר שרתי אחסון כשצריך או כשמרחב המפתחות מתרחב. פיצולים שנוצרו כדי לטפל בעודף תנועה נשמרים למשך כ-24 שעות, גם אם התנועה נעלמת. לכן, אם יש עליות חוזרות בתנועה, הפיצולים נשמרים ופיצולים נוספים מוצגים כשנדרש. המנגנונים האלה עוזרים למסדי נתונים לבצע שינוי גודל אוטומטי (autoscaling) ככל שעומס התנועה או גודל מסד הנתונים גדלים.Cloud Firestore עם זאת, יש כמה מגבלות שכדאי להכיר, כפי שמפורט בהמשך.
פיצול האחסון והטעינה לוקח זמן, והגדלת נפח התנועה מהר מדי עלולה לגרום לזמן אחזור גבוה או לשגיאות של חריגה מהזמן הקצוב לתפוגה, שנקראות בדרך כלל נקודות חמות, בזמן שהשירות מבצע התאמות. השיטה המומלצת היא לפזר את הפעולות על פני טווח המפתחות, תוך הגדלת התנועה באוסף במסד נתונים עם 500 פעולות בשנייה. אחרי העלייה ההדרגתית הזו, מגדילים את התנועה ב-50% כל חמש דקות. התהליך הזה נקרא כלל 500/50/5, והוא מאפשר למסד הנתונים להתרחב בצורה אופטימלית כדי לעמוד בעומס העבודה.
למרות שהפיצולים נוצרים באופן אוטומטי עם העלייה בעומס, Cloud Firestore יכול לפצל טווח מפתחות רק עד שהוא משרת מסמך יחיד באמצעות קבוצה ייעודית של שרתי אחסון משוכפלים. כתוצאה מכך, נפחים גבוהים ומתמשכים של פעולות בו-זמניות במסמך יחיד עלולים להוביל לנקודה חמה במסמך הזה. אם נתקלתם בחביון גבוה באופן קבוע במסמך יחיד, כדאי לשקול לשנות את מודל הנתונים כדי לפצל את הנתונים או לשכפל אותם בכמה מסמכים.
שגיאות של התנגשות מתרחשות כשכמה פעולות מנסות לקרוא ו/או לכתוב את אותו מסמך בו-זמנית.
מקרה מיוחד נוסף של יצירת נקודות חמות מתרחש כשמשתמשים במפתח עם ערכים עולים או יורדים ברצף כמזהה המסמך ב-Cloud Firestore, ויש מספר גבוה במיוחד של פעולות בשנייה. יצירת פיצולים נוספים לא תעזור במקרה הזה, כי העלייה החדה בתנועה פשוט תעבור לפיצול החדש שנוצר. מכיוון ש-Cloud Firestore יוצר אינדקס אוטומטי לכל השדות במסמך כברירת מחדל, יכול להיות שגם במרחב האינדקס ייווצרו נקודות חמות כאלה לשדה במסמך שמכיל ערך שעולה או יורד באופן רציף, כמו חותמת זמן.
שימו לב שאם תפעלו לפי השיטות המומלצות שצוינו למעלה, Cloud Firestore יוכל להתרחב כדי לטפל בעומסי עבודה גדולים ככל שיידרש, בלי שתצטרכו לשנות את ההגדרות.
פתרון בעיות
Cloud Firestore מספק את Key Visualizer ככלי אבחון שנועד לנתח דפוסי שימוש ולפתור בעיות שקשורות לנקודות חמות.