מומלץ לקרוא את המסמך הזה כדי לקבל החלטות מושכלות לגבי תכנון הארכיטקטורה של האפליקציות שלכם, כך שיספקו ביצועים גבוהים ואמינות. המסמך הזה כולל נושאים מתקדמים בנושא Cloud Firestore. אם אתם רק מתחילים להשתמש ב-Cloud Firestore, כדאי לעיין במקום זאת במדריך למתחילים.
Cloud Firestore הוא מסד נתונים גמיש וניתן להתאמה לפיתוח של מכשירים ניידים, אתרים ושרתים מ-Firebase ו-Google Cloud. קל מאוד להתחיל לעבוד עם Cloud Firestore ולכתוב אפליקציות עשירות וחזקות.
כדי לוודא שהאפליקציות ימשיכו לפעול בצורה טובה ככל שגודל מסד הנתונים והתנועה יגברו, כדאי להבין את המנגנונים של קריאה וכתיבה בקצה העורפי של Cloud Firestore. חשוב גם להבין את האינטראקציה של פעולות הקריאה והכתיבה עם שכבת האחסון ואת האילוצים הבסיסיים שעשויים להשפיע על הביצועים.
לפני שמתחילים בתכנון הארכיטקטורה של האפליקציה, כדאי לעיין בשיטות המומלצות שמפורטות בקטעים הבאים.
הסבר על הרכיבים ברמה גבוהה
בתרשים הבא מוצגים הרכיבים ברמה גבוהה שקשורים לבקשת API של Cloud Firestore.
Cloud Firestore ערכות SDK וספריות לקוח
Cloud Firestore תומך בערכות SDK ובספריות לקוח לפלטפורמות שונות. אפליקציה יכולה לבצע קריאות HTTP ו-RPC ישירות ל-API Cloud Firestore, אבל ספריות הלקוח מספקות שכבת הפשטה כדי לפשט את השימוש ב-API ולהטמיע שיטות מומלצות. יכול להיות שהן גם מספקות תכונות נוספות כמו גישה אופליין, מטמון וכו'.
ממשק קצה של Google (GFE)
זהו שירות תשתית המשותף לכל שירותי Google Cloud. 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: המסמכים מאוחסנים בטבלה הזו.
- הטבלה Indexes: בטבלה הזו מאוחסנות רשומות אינדקס שמאפשרות לקבל תוצאות ביעילות ולמיין אותן לפי ערך האינדקס.
בתרשים הבא אפשר לראות איך הטבלאות של מסד נתונים Cloud Firestore עשויות להיראות עם הפיצולים. הפילוחים מוכפלים בשלושה תחומים שונים, וכל פילוח מוקצה ל-leader של Paxos.
אזור יחיד לעומת מספר אזורים
כשיוצרים מסד נתונים, צריך לבחור אזור או מספר אזורים.
מיקום אזורי יחיד הוא מיקום גיאוגרפי ספציפי, כמו us-west1. לפיצולים של הנתונים של מסד נתונים מסוג Cloud Firestore יש רפליקות באזורים שונים בתוך האזור שנבחר, כפי שהוסבר למעלה.
מיקום במספר אזורים מורכב מקבוצה מוגדרת של אזורים שבהם נשמרות רפליקות של מסד הנתונים. בפריסה של Cloud Firestore במספר אזורים, בשני האזורים יש רפליקות מלאות של כל הנתונים במסד הנתונים. באזור שלישי יש עותק מראה שלא שומר קבוצה מלאה של נתונים, אבל משתתף ברפליקה. כשמשכפלים את הנתונים בין כמה אזורים, אפשר לכתוב ולקרוא אותם גם אם אזור שלם מושבת.
מידע נוסף על המיקומים של אזור זמין במאמר מיקומי Cloud Firestore.
הסבר על תהליך הכתיבה ב-Cloud Firestore
לקוח Cloud Firestore יכול לכתוב נתונים על ידי יצירת מסמך יחיד, עדכון שלו או מחיקה שלו. כדי לכתוב במסמך יחיד, צריך לעדכן את המסמך ואת רשומות האינדקס המשויכות אליו באופן אטומי בשכבת האחסון. Cloud Firestore תומך גם בפעולות אטומיות שמכילות כמה פעולות קריאה ו/או כתיבה במסמך אחד או יותר.
לכל סוגי הכתיבה, Cloud Firestore מספק את מאפייני ACID (אטומיות, עקביות, בידוד ועמידות) של מסדי נתונים יחסיים. Cloud Firestore מספק גם יכולת ביצוע בסדר, כלומר כל העסקאות מופיעות כאילו בוצעו בסדר טורני.
השלבים ברמת העל בעסקת כתיבה
כשלקוח Cloud Firestore מבצע פעולת כתיבה או מבצע התחייבות לעסקה באמצעות אחת מהשיטות שצוינו למעלה, הפעולה הזו מתבצעת באופן פנימי כעסקת קריאה-כתיבה של מסד נתונים בשכבת האחסון. העסקה מאפשרת ל-Cloud Firestore לספק את מאפייני ACID שצוינו למעלה.
בשלב הראשון של העסקה, Cloud Firestore קורא את המסמך הקיים ומחליט אילו מוטציות לבצע בנתונים בטבלה Documents.
העדכונים כוללים גם עדכונים נדרשים בטבלה Indexes באופן הבא:
- שדות שנוספים למסמכים צריכים להוסיף ערכים תואמים לטבלת האינדקסים.
- שדות שמסירים מהמסמכים צריך למחוק גם בטבלה Indexes.
- שדות שמשתנים במסמכים צריכים גם מחיקה (של ערכים ישנים) וגם הוספה (של ערכים חדשים) בטבלת האינדקסים.
כדי לחשב את המוטציות שצוינו קודם, הפונקציה Cloud Firestore קוראת את הגדרת ההוספה לאינדקס של הפרויקט. בהגדרת ההוספה לאינדקס מאוחסן מידע על האינדקסים של הפרויקט. ב-Cloud Firestore נעשה שימוש בשני סוגי אינדקסים: שדה יחיד ומורכב. הסבר מפורט על האינדקסים שנוצרים ב-Cloud Firestore זמין במאמר סוגי אינדקסים ב-Cloud Firestore.
אחרי שמחשבים את המוטציות, Cloud Firestore אוסף אותן בתוך עסקה ולאחר מכן מבצע עליה התחייבות (commit).
הסבר על עסקת כתיבה בשכבת האחסון
כפי שצוין קודם, כתיבת נתונים ב-Cloud Firestore כוללת עסקת קריאה-כתיבה בשכבת האחסון. בהתאם לפריסה של הנתונים, פעולת כתיבה עשויה לכלול פיצול אחד או יותר, כפי שמתואר בפריסת הנתונים.
בתרשים הבא, למסד הנתונים Cloud Firestore יש שמונה פלחים (מסומנים בספרות 1-8) שמתארחים בשלושה שרתי אחסון שונים באזור אחד, וכל פלח משכפל ב-3 אזורים שונים(או יותר). לכל חלוקה יש מנהיג 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. יש עסקה מבוזרת, שכוללת את כל הפיצולים האלה כמשתתפים. חלוקות המשתתפים עשויות לכלול גם כל חלוקה אחרת שממנה נתונים נקראו מוקדם יותר כחלק מהעסקה לקריאה וכתיבה.
השלבים הבאים מתארים מה קורה כחלק מההתחייבות:
- לקוח האחסון מבצע השמירה (commit). השמירה מכילה את המוטציות M1 עד M5.
- המחיצות 3 ו-6 הן המשתתפות בעסקה הזו. אחד מהמשתתפים נבחר בתור הרכז, למשל 'חלוקה 3'. התפקיד של התיאום הוא לוודא שהעסקה מתבצעת או מבוטלת באופן אטומי בכל המשתתפים.
- הרפליקות המובילות של הפיצולים האלה אחראיות על העבודה של המשתתפים והתיאמים.
- כל משתתף ומתאם מפעיל אלגוריתם Paxos עם הרפליקות שלהם.
- המארח המוביל מפעיל אלגוריתם Paxos עם הרפליקות. רוב העותקים המבוססים על אותה תבנית משיבים עם תגובה מסוג
ok to commit
ליומן המאסטר, וכך מתקבל רוב נדרש. - לאחר מכן, כל משתתף מודיע לרכז שהוא מוכן (השלב הראשון של אישור בשני שלבים). אם אחד מהמשתתפים לא יכול לבצע את העסקה, העסקה כולה
aborts
.
- המארח המוביל מפעיל אלגוריתם Paxos עם הרפליקות. רוב העותקים המבוססים על אותה תבנית משיבים עם תגובה מסוג
- אחרי שהרכז יודע שכל המשתתפים, כולל הוא עצמו, מוכנים, הוא מודיע לכל המשתתפים על תוצאת העסקה
accept
(שלב שני של אישור שתי שלבים). בשלב הזה, כל משתתף מתעד את החלטת ההתחייבות באחסון יציב והעסקה מתחייבת. - התיאום משיב ללקוח האחסון ב-Cloud Firestore שהעסקה בוצעה. במקביל, התאמות הנתונים חלות על ידי התיאום ועל ידי כל המשתתפים.
כשמסד הנתונים Cloud Firestore קטן, יכול להיות שחלוקה אחת תהיה הבעלים של כל המפתחות במוּטציות M1 עד M5. במקרה כזה, יש רק משתתף אחד בעסקה ולא נדרש אישור בשני שלבים שצוין קודם, כך שהכתיבה מהירה יותר.
כתיבה במספר אזורים
בפריסה בכמה אזורים, הפצת הרפליקות בין האזורים מגדילה את הזמינות, אבל יש לכך עלות בביצועים. זמן הנסיעה הלוך ושוב (round trip) בתקשורת בין רפליקות באזורים שונים ארוך יותר. לכן, זמן האחזור הבסיסי של פעולות Cloud Firestore ארוך יותר בהשוואה לפריסות באזור יחיד.
אנחנו מגדירים את הרפליקות כך שהמנהיגות של חלוקות תמיד תישאר באזור הראשי. האזור הראשי הוא האזור שממנו מגיעה התנועה לשרת Cloud Firestore. ההחלטה הזו על מנהיגות מפחיתה את זמן האחזור הלוך ושוב בתקשורת בין לקוח האחסון ב-Cloud Firestore לבין מנהיג הרפליקה (או התיאום של עסקאות עם חלוקה לכמה חלקים).
כל פעולת כתיבה ב-Cloud Firestore כוללת גם אינטראקציה מסוימת עם המנוע בזמן אמת ב-Cloud Firestore. מידע נוסף על שאילתות בזמן אמת זמין במאמר הסבר על שאילתות בזמן אמת בקנה מידה נרחב.
הסבר על מחזור החיים של קריאה ב-Cloud Firestore
בקטע הזה נסביר על קריאות עצמאיות ולא בזמן אמת ב-Cloud Firestore. באופן פנימי, שרת Cloud Firestore מטפל ברוב השאילתות האלה בשני שלבים עיקריים:
- סריקה של טווח יחיד בטבלה Indexes
- חיפוש לפי נקודות בטבלה Documents על סמך תוצאת הסריקה הקודמת
הקריאה של הנתונים משכבת האחסון מתבצעת באופן פנימי באמצעות עסקה במסד נתונים, כדי להבטיח קריאה עקבית. עם זאת, בניגוד לעסקאות שמשמשות לכתיבה, העסקאות האלה לא נעולות. במקום זאת, הם בוחרים חותמת זמן ומבצעים את כל הקריאות בחותמת הזמן הזו. מכיוון שהן לא מקבלות מנעולים, הן לא חוסמות טרנזקציות קריאה-כתיבה בו-זמניות. כדי לבצע את העסקה הזו, לקוח האחסון ב-Cloud Firestore מציין גבול של חותמת זמן, שמציין לשכבת האחסון איך לבחור חותמת זמן לקריאה. סוג המגבלה של חותמת הזמן שנבחרת על ידי לקוח האחסון ב-Cloud Firestore נקבע לפי אפשרויות הקריאה של בקשת הקריאה.
הסבר על עסקת קריאה בשכבת האחסון
בקטע הזה מתוארים סוגי הקריאות ואופן העיבוד שלהן בשכבת האחסון ב-Cloud Firestore.
קריאות חזקות
כברירת מחדל, קריאות ל-Cloud Firestore הן בעלות עקביות חזקה. בעקביות החזקה הזו, קריאה של Cloud Firestore מחזירה את הגרסה העדכנית ביותר של הנתונים שמשקפת את כל פעולות הכתיבה שהתחייבו עד לתחילת הקריאה.
קריאה של פיצול יחיד
לקוח האחסון ב-Cloud Firestore מחפש את הפיצולים שבבעלותם המפתחות של השורות שרוצים לקרוא. נניח שהוא צריך לבצע קריאה מחלוקה 3 מהקטע הקודם. הלקוח שולח את בקשת הקריאה לריפליקה הקרובה ביותר כדי לקצר את זמן האחזור הלוך ושוב.
בשלב הזה, יכולות להתרחש התרחישים הבאים בהתאם לרפליקת שנבחרה:
- בקשת הקריאה מועברת לעותק מוביל (אזור א').
- מכיוון שהמוביל תמיד מעודכן, הקריאה יכולה להתבצע ישירות.
- בקשת הקריאה מועברת לריפליקה שאינה מנהיגה (למשל, תחום B)
- יכול להיות שחלוקה 3 תדע לפי המצב הפנימי שלה שיש לה מספיק מידע כדי לשרת את הקריאה, והחלוקה תעשה זאת.
- לא ברור לחלק 3 אם הוא ראה את הנתונים האחרונים. הוא שולח הודעה ללידר כדי לבקש את חותמת הזמן של העסקה האחרונה שהוא צריך להחיל כדי להציג את הקריאה. אחרי שהעסקה הזו תיושם, הקריאה תוכל להמשיך.
Cloud Firestore מחזירה את התשובה ללקוח שלה.
קריאה עם פיצול מרובים
במצב שבו צריך לבצע את הקריאות מכמה פיצולים, אותו מנגנון מתרחש בכל הפיצולים. אחרי שהנתונים יחזרו מכל הפיצולים, לקוח האחסון ב-Cloud Firestore ישלב את התוצאות. לאחר מכן, Cloud Firestore משיב ללקוח שלו עם הנתונים האלה.
קריאות לא עדכניות
קריאות חזקות הן מצב ברירת המחדל ב-Cloud Firestore. עם זאת, היתרון הזה מגיע עם עלות של זמן אחזור ארוך יותר, בגלל הצורך בתקשורת עם המארח. לרוב, לאפליקציית Cloud Firestore אין צורך לקרוא את הגרסה העדכנית ביותר של הנתונים, והפונקציונליות פועלת היטב עם נתונים שעשויים להיות לא עדכניים לכמה שניות.
במקרה כזה, הלקוח יכול לבחור לקבל קריאות לא עדכניות באמצעות אפשרויות הקריאה read_time
. במקרה כזה, הקריאות מתבצעות כפי שהנתונים היו ב-read_time
, וסביר מאוד שהרפליקה הקרובה ביותר כבר אימתה שיש לה נתונים ב-read_time
שצוין.
כדי לשפר את הביצועים באופן משמעותי, ערך סביר של סטלות הוא 15 שניות. גם בקריאות לא עדכניות, השורות שהתקבלו עקביות זו לזו.
הימנעות מנקודות חמות
הפיצולים ב-Cloud Firestore מחולקים באופן אוטומטי לחלקים קטנים יותר כדי לחלק את העבודה של שירות התנועה בין שרתי אחסון נוספים לפי הצורך או כשמרחב המפתחות מתרחב. חלוקות שנוצרות כדי לטפל בתנועה עודפת נשמרות למשך כ-24 שעות, גם אם נפח התנועה פוחת. לכן, אם יש עליות חדות חוזרות ונשנות בנפח התנועה, חלוקות הניסוי נשמרות וחלוקות נוספות מתווספות לפי הצורך. המנגנונים האלה עוזרים למסדי הנתונים של Cloud Firestore להתאים את עצמם באופן אוטומטי לעומס התנועה או לגודל מסד הנתונים. עם זאת, יש כמה מגבלות שכדאי לדעת עליהן, כפי שמוסבר בהמשך.
חלוקת האחסון והעומס אורכת זמן, והגדלת נפח התנועה מהר מדי עלולה לגרום לזמן אחזור ארוך או לשגיאות מסוג 'חרגה ממכסת הזמן', שנקראות בדרך כלל נקודות חמות, בזמן שהשירות מתאים את עצמו. השיטה המומלצת היא לפזר את הפעולות בטווח המפתחות, תוך הגדלת נפח התנועה באוסף במסד נתונים עם 500 פעולות לשנייה. לאחר העלייה ההדרגתית הזו, מומלץ להגדיל את נפח התנועה ב-50% בכל חמש דקות. התהליך הזה נקרא כלל 500/50/5, והוא מאפשר להתאים את מסד הנתונים בצורה אופטימלית לעומס העבודה.
אמנם הפיצולים נוצרים באופן אוטומטי ככל שהעומס גדל, אבל Cloud Firestore יכול לפצל טווח מפתחות רק עד שהוא משרת מסמך יחיד באמצעות קבוצה ייעודית של שרתי אחסון עם רפליקה. כתוצאה מכך, נפח גבוה ומתמשך של פעולות בו-זמניות במסמך יחיד עלול להוביל לנקודת חיכוך במסמך הזה. אם נתקלתם בזמני אחזור ארוכים באופן קבוע במסמך יחיד, כדאי לשקול לשנות את מודל הנתונים כדי לפצל או לשכפל את הנתונים במספר מסמכים.
שגיאות התנגשויות מתרחשות כשמספר פעולות מנסים לקרוא או לכתוב את אותו מסמך בו-זמנית.
מקרה מיוחד נוסף של יצירת צווארי בקבוק מתרחש כשמשתמשים במפתח שמתגבר או פוחת באופן רציף בתור מזהה המסמך ב-Cloud Firestore, ויש מספר גבוה במיוחד של פעולות לשנייה. יצירת עוד חלוקות לא תעזור במקרה כזה, כי גל התנועה פשוט יעבור לחלוקה החדשה שנוצרה. מאחר ש-Cloud Firestore יוצר באופן אוטומטי אינדקס של כל השדות במסמך כברירת מחדל, יכול להיות שייווצרו נקודות חמות נעות כאלה במרחב האינדקס גם בשדה של מסמך שמכיל ערך שמתגבר או פוחת באופן רציף, כמו חותמת זמן.
חשוב לזכור: אם תפעלו לפי השיטות שמפורטות למעלה, תוכלו להגדיל את Cloud Firestore כדי לטפל בעומסי עבודה גדולים באופן שרירותי, בלי שתצטרכו לשנות את ההגדרות.
פתרון בעיות
Cloud Firestore מספק את כלי התצוגה החזותית של מפתחות ככלי אבחון שנועד לנתח דפוסי שימוש ולפתור בעיות של נקודות חמות.