הבנת קריאה וכתיבה בקנה מידה נרחב

מומלץ לקרוא את המסמך הזה כדי לקבל החלטות מושכלות לגבי תכנון הארכיטקטורה של האפליקציות שלכם, כך שיספקו ביצועים גבוהים ואמינות. המסמך הזה כולל נושאים מתקדמים בנושא 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 להסכמה מנהלים את היצירה של רפליקות עקביות של העותק המפוצל. העתק אחד של כל פיצול נבחר לשמש כמנהיג פקסו, שאחראי לטיפול בכתיבה לקבוצה. שכפול הסינכרוני מאפשר לך תמיד לקרוא את הגרסה האחרונה של הנתונים מ-Cloud Firestore.

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

פריסת הנתונים

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

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

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

פריסת הנתונים

אזור יחיד לעומת מספר אזורים

כשיוצרים מסד נתונים, צריך לבחור אזור או מספר אזורים.

מיקום אזורי יחיד הוא מיקום גיאוגרפי ספציפי, כמו 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 אוסף אותם בעסקה ואז שומר אותה.

הסבר על עסקת כתיבה בשכבת האחסון

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

בתרשים הבא, למסד הנתונים Cloud Firestore יש שמונה פלחים (מסומנים בספרות 1-8) שמתארחים בשלושה שרתי אחסון שונים באזור אחד, וכל פלח עובר רפליקה ב-3 אזורים שונים(או יותר). לכל חלוקה יש מנהיג Paxos, שיכול להיות באזור אחר בחלוקות שונות.

<span class=פיצול מסד הנתונים של Cloud Firestore">

נניח שיש לכם מסד נתונים Cloud Firestore שמכיל את האוסף Restaurants:

אוסף מסעדות

לקוח Cloud Firestore מבקש לבצע את השינוי הבא במסמך באוסף Restaurant על ידי עדכון הערך של השדה priceCategory.

מעבר למסמך באוסף

השלבים הכלליים הבאים מתארים מה קורה במסגרת הכתיבה:

  1. יוצרים טרנזקציה לקריאה וכתיבה.
  2. קריאת המסמך restaurant1 באוסף Restaurants מהטבלה Documents בשכבת האחסון.
  3. קוראים את האינדקסים של המסמך מהטבלה Indexes.
  4. חישוב המוטציות שיבוצעו בנתונים. במקרה הזה, יש חמש מוטציות:
    • M1: מעדכנים את השורה של restaurant1 בטבלה Documents כך שתשקף את השינוי בערך בשדה priceCategory.
    • M2 ו-M3: מוחקים את השורות של הערך הישן priceCategory בטבלה Indexes עבור אינדקסים יורדים ועולים.
    • M4 ו-M5: מוסיפים את השורות של הערך החדש priceCategory לטבלה Indexes עבור אינדקסים יורדים ועולים.
  5. שומרים את המוטציות האלה.

לקוח האחסון בשירות Cloud Firestore מחפש את הפיצולים שבבעלותם המפתחות של השורות שרוצים לשנות. נבחן מצב שבו Split 3 ממלאת בקשות M1 ו-Split 6 מציגה את M2-M5. יש עסקה מבוזרת, שכוללת את כל הפיצולים האלה כמשתתפים. חלוקות המשתתפים עשויות לכלול גם כל חלוקה אחרת שממנה נתונים נקראו מוקדם יותר כחלק מהעסקה לקריאה וכתיבה.

השלבים הבאים מתארים מה קורה כחלק מההתחייבות:

  1. לקוח האחסון מבצע השמירה (commit). השמירה מכילה את המוטציות M1 עד M5.
  2. המחיצות 3 ו-6 הן המשתתפות בעסקה הזו. אחד מהמשתתפים נבחר בתור הרכז, למשל 'חלוקה 3'. התפקיד של התיאום הוא לוודא שהעסקה מתבצעת או מבוטלת באופן אטומי בכל המשתתפים.
    • העתקים של המנהיגים האלו אחראים לעבודה של המשתתפים והמתאמים.
  3. כל משתתף ומתאם מפעיל אלגוריתם Paxos עם הרפליקות שלהם.
    • המארח המוביל מפעיל אלגוריתם Paxos עם הרפליקות. רוב העותקים המבוססים על אותה תבנית יגיבו עם תגובה מסוג ok to commit ליומן המנהיג.
    • לאחר מכן כל משתתף מודיע לרכז שהוא מוכן (השלב הראשון של אישור בשני שלבים). אם אחד מהמשתתפים לא יכול לבצע את העסקה, העסקה כולה aborts.
  4. אחרי שהרכז יודע שכל המשתתפים, כולל הוא עצמו, מוכנים, הוא מודיע לכל המשתתפים על תוצאת העסקה accept (שלב שני של אישור בשני שלבים). בשלב הזה, כל משתתף מתעד את החלטת ההתחייבות באחסון יציב והעסקה מתחייבת.
  5. התיאום משיב ללקוח האחסון ב-Cloud Firestore שהעסקה בוצעה. במקביל, התאמות הנתונים חלות על ידי התיאום ועל ידי כל המשתתפים.

מחזור החיים של השמירה (commit)

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

כתיבה במספר אזורים

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

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

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

הסבר על מחזור החיים של קריאה ב-Cloud Firestore

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

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

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

הסבר על עסקת קריאה בשכבת האחסון

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

קריאות חזקות

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

קריאה של פיצול יחיד

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

בשלב הזה, יכולים להתרחש התרחישים הבאים בהתאם לרפליקת שנבחרה:

  • בקשת הקריאה מועברת לרפליקציית מנהיג (Zone A).
    • מכיוון שהמוביל תמיד מעודכן, הקריאה יכולה להתבצע ישירות.
  • בקשת הקריאה מועברת לריפליקה שאינה מנהיגה (למשל, תחום 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 וממקם את מסד הנתונים כך שיתאים לעומס (scaling) באופן אופטימלי כדי לעמוד בעומס העבודה שלכם.

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

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

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

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

פתרון בעיות

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

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