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

ערכות SDK וספריות לקוח של Cloud Firestore
Cloud Firestore תומך בערכות SDK ובספריות לקוח לפלטפורמות שונות. אפליקציה יכולה לבצע קריאות HTTP ו-RPC ישירות ל-API של Cloud Firestore, אבל ספריות הלקוח מספקות שכבת הפשטה כדי לפשט את השימוש ב-API ולהטמיע שיטות מומלצות. הם יכולים גם לספק תכונות נוספות כמו גישה אופליין, מטמונים וכו'.
ממשק הקצה של Google (GFE)
זהו שירות תשתית שמשותף לכל שירותי הענן של Google. ה-GFE מקבל בקשות נכנסות ומעביר אותן לשירות Google הרלוונטי (שירות Cloud Firestore בהקשר הזה). הוא גם מספק פונקציות חשובות אחרות, כולל הגנה מפני התקפות מניעת שירות.
שירות אחד (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 עשויות להיראות עם הפיצולים. הפיצולים משוכפלים בשלושה אזורים שונים, ולכל פיצול מוקצה מנהיג 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.
- אם מסירים שדות מהמסמכים, צריך למחוק את השדות התואמים בטבלת האינדקסים.
- בשדות שמשתנים במסמכים, צריך גם למחוק (את הערכים הישנים) וגם להוסיף (את הערכים החדשים) בטבלה Indexes.
כדי לחשב את השינויים שצוינו קודם, Cloud Firestore קורא את הגדרת ההוספה לאינדקס של מסד הנתונים. הגדרת הוספה לאינדקס מאחסנת מידע על האינדקסים של מסד נתונים. ב-Cloud Firestore יש שני סוגים של אינדקסים: אינדקסים של שדה יחיד ואינדקסים מורכבים. למידע מפורט על האינדקסים שנוצרו ב-Cloud Firestore, אפשר לעיין במאמר סוגי אינדקסים ב-Cloud Firestore.
אחרי שהמוטציות מחושבות, Cloud Firestore אוסף אותן בתוך טרנזקציה ואז מבצע אותה.
הסבר על עסקת כתיבה בשכבת האחסון
כמו שהסברנו קודם, פעולת כתיבה ב-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. ה-commit מכיל את המוטציות M1-M5.
- המשתתפים בעסקה הזו הם חלוקות 3 ו-6. אחד מהמשתתפים נבחר בתור המתאם, למשל Split 3. תפקיד המתאם הוא לוודא שהטרנזקציה מתבצעת או מבוטלת באופן אטומי בכל המשתתפים.
- הרפליקות המובילות של הפיצולים האלה אחראיות לעבודה שמבצעים המשתתפים והרכזים.
- כל משתתף ורכז מריצים אלגוריתם Paxos עם הרפליקות שלהם.
- ה-leader מריץ אלגוריתם Paxos עם הרפליקות. הקוורום מושג אם רוב הרפליקות משיבות ל-leader בתגובת
ok to commit. - לאחר מכן, כל משתתף מודיע למתאם כשהוא מוכן (השלב הראשון של אישור דו-שלבי). אם אחד מהמשתתפים לא יכול לבצע את הטרנזקציה, הטרנזקציה כולה
aborts.
- ה-leader מריץ אלגוריתם Paxos עם הרפליקות. הקוורום מושג אם רוב הרפליקות משיבות ל-leader בתגובת
- אחרי שהרכז יודע שכל המשתתפים, כולל הוא עצמו, מוכנים, הוא מעביר את תוצאת העסקה
acceptלכל המשתתפים (השלב השני של אישור דו-שלבי). בשלב הזה, כל משתתף מתעד את החלטת האישור באחסון יציב והטרנזקציה מאושרת. - הרכז מגיב ללקוח האחסון ב-Cloud Firestore שהעסקה בוצעה. במקביל, הרכז וכל המשתתפים מחילים את השינויים על הנתונים.

כאשר מסד הנתונים Cloud Firestore קטן, יכול להיות שפיצול אחד יהיה הבעלים של כל המפתחות במוטציות M1-M5. במקרה כזה, יש רק משתתף אחד בעסקה ואין צורך ב-two-phase commit שהוזכר קודם, כך שהכתיבה מהירה יותר.
פעולות כתיבה במספר אזורים
בפריסה במספר אזורים, פיזור הרפליקות בין האזורים מגדיל את הזמינות, אבל יש לזה מחיר מבחינת הביצועים. התקשורת בין רפליקות באזורים שונים נמשכת זמן רב יותר. לכן, זמן האחזור הבסיסי לפעולות של 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 מהקטע הקודם. הלקוח שולח את בקשת הקריאה לרפליקה הקרובה ביותר כדי לצמצם את זמן האחזור של הלוך ושוב.
בשלב הזה, יכולים לקרות המקרים הבאים, בהתאם לרפליקה שנבחרה:
- בקשת הקריאה מגיעה לרפליקה הראשית (אזור א').
- מכיוון שה-Leader תמיד מעודכן, אפשר להמשיך ישירות לקריאה.
- בקשת הקריאה מגיעה לרפליקה שאינה מובילה (למשל, אזור B)
- יכול להיות שפיצול 3 יודע לפי המצב הפנימי שלו שיש לו מספיק מידע כדי להציג את הקריאה, והפיצול עושה זאת.
- בפיצול 3 לא בטוחים אם הם ראו את הנתונים העדכניים ביותר. הוא שולח הודעה ל-leader כדי לבקש את חותמת הזמן של הטרנזקציה האחרונה שהוא צריך להחיל כדי להציג את הקריאה. אחרי שהטרנזקציה הזו מוחלת, אפשר להמשיך בקריאה.
Cloud Firestore ואז מחזיר את התשובה ללקוח שלו.
קריאה מפוצלת מרובה
במצב שבו צריך לבצע את הקריאות מכמה פיצולים, אותו מנגנון מתרחש בכל הפיצולים. אחרי שהנתונים מוחזרים מכל הפיצולים, לקוח האחסון ב-Cloud Firestore משלב את התוצאות. לאחר מכן, Cloud Firestore מגיב ללקוח עם הנתונים האלה.
קריאות בעבר
קריאות חזקות הן מצב ברירת המחדל ב-Cloud Firestore. עם זאת, החיסרון הוא זמן אחזור ארוך יותר, בגלל התקשורת שנדרשת עם ה-leader. במקרים רבים, האפליקציה של 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 יש כלי אבחון שנקרא Key Visualizer, שנועד לנתח דפוסי שימוש ולפתור בעיות של נקודות חמות.