NDB מנהל את מטמון הנתונים בשבילכם. יש שתי רמות של מטמון: מטמון בהקשר ומטמון שמשמש כשער לשירות המטמון הרגיל של App Engine, memcache. שני סוגי המטמון מופעלים כברירת מחדל לכל סוגי הישויות, אבל אפשר להגדיר אותם בהתאם לצרכים מתקדמים. בנוסף, NDB מטמיע תכונה שנקראת auto-batching, שמנסה לקבץ פעולות יחד כדי לצמצם את מספר הפעמים שהנתונים עוברים בין הלקוח לשרת.
מבוא
שמירת נתונים במטמון עוזרת לרוב סוגי האפליקציות. NDB שומרת במטמון באופן אוטומטי נתונים שהיא כותבת או קוראת (אלא אם האפליקציה מוגדרת אחרת). קריאה מהמטמון מהירה יותר מקריאה מ-Datastore.
אפשר לשנות את התנהגות הקאשינג של הרבה פונקציות NDB על ידי העברת ארגומנטים של אפשרויות הקשר.
לדוגמה, אפשר להתקשר אל
key.get(use_cache=False, use_memcache=False)
כדי לעקוף את השמירה במטמון. אפשר גם לשנות את מדיניות ברירת המחדל של השמירה במטמון בהקשר של NDB, כמו שמתואר בהמשך.
זהירות: כשמשתמשים בכלי Datastore Viewer במסוף הניהול כדי לשנות את התוכן של Datastore, הערכים שנשמרו במטמון לא מתעדכנים. לכן, יכול להיות שהמטמון לא יהיה עקבי. בדרך כלל זה לא מהווה בעיה במטמון בהקשר. ב-Memcache, מומלץ להשתמש במסוף הניהול כדי לרוקן מידע (Flush) את המטמון.
אובייקטים של הקשר
ניהול המטמון מתבצע באמצעות מחלקה בשם Context. כל שרשור וכל טרנזקציה מופעלים בהקשר חדש. מכיוון שכל בקשת HTTP נכנסת מתחילה שרשור חדש, כל בקשה מופעלת גם בהקשר חדש. כדי לגשת להקשר הנוכחי, משתמשים בפונקציה ndb.get_context().
זהירות: אין טעם לשתף אובייקטים של Context בין כמה שרשורים או בקשות.
אל תשמרו את ההקשר כמשתנה גלובלי!
אפשר לאחסן אותו במשתנה מקומי או במשתנה מקומי לשרשור.
לאובייקטים של הקשר יש שיטות להגדרת מדיניות מטמון ולביצוע מניפולציות אחרות במטמון.
המטמון בהקשר
המטמון בהקשר נשמר רק למשך השרשור. כלומר, לכל בקשת HTTP נכנסת מוקצה מטמון חדש בהקשר, והוא 'גלוי' רק לקוד שמטפל בבקשה הזו. אם האפליקציה יוצרת שרשורים נוספים בזמן הטיפול בבקשה, גם לשרשורים האלה יהיה מטמון חדש ונפרד בהקשר.
המטמון בהקשר מהיר, והוא נמצא בזיכרון. כשפונקציית NDB כותבת ל-Datastore, היא כותבת גם למטמון בהקשר. כשפונקציית NDB קוראת ישות, היא בודקת קודם את המטמון בהקשר. אם הישות נמצאת שם, לא מתבצעת אינטראקציה עם Datastore.
כשפונקציית NDB שולחת שאילתה ל-Datastore, רשימת התוצאות מאוחזרת מ-Datastore. עם זאת, אם תוצאה כלשהי נמצאת במטמון בהקשר, נעשה בה שימוש במקום בערך שאוחזר משאילתת Datastore. תוצאות השאילתה נכתבות חזרה למטמון בהקשר אם מדיניות המטמון קובעת זאת (אבל אף פעם לא ל-Memcache).
Memcache
Memcache הוא שירות המטמון הרגיל של App Engine. הוא מהיר יותר מ-Datastore אבל איטי יותר ממטמון בתוך ההקשר (אלפיות השנייה לעומת מיליוניות השנייה).
כברירת מחדל, בהקשר לא טרנזקציונלי, כל הישויות נשמרות במטמון ב-memcache. כל ההקשרים של האפליקציה משתמשים באותו שרת memcache ורואים קבוצה עקבית של ערכים במטמון.
Memcache לא תומך בעסקאות. לכן, יכול להיות שעדכון שנועד להתבצע גם ב-Datastore וגם ב-Memcache יתבצע רק באחד מהם. כדי לשמור על עקביות במקרים כאלה (יכול להיות שזה יפגע בביצועים), הישות המעודכנת נמחקת מ-Memcache ואז נכתבת ב-Datastore. פעולת קריאה שתתבצע לאחר מכן תגלה שהישות חסרה ב-Memcache, תאחזר אותה מ-Datastore ואז תעדכן אותה ב-Memcache כתוצאה לוואי של הקריאה. בנוסף, קריאות NDB בתוך עסקאות מתעלמות מ-Memcache.
כשכותבים ישויות בתוך טרנזקציה, לא נעשה שימוש ב-memcache. כשמבצעים את הטרנזקציה, ההקשר שלה ינסה למחוק את כל הישויות האלה מ-memcache. עם זאת, חשוב לזכור שיכול להיות שחלק מהכשלים ימנעו את המחיקות האלה.
פונקציות של מדיניות
שמירה אוטומטית במטמון נוחה לרוב האפליקציות, אבל יכול להיות שהאפליקציה שלכם לא רגילה ואתם רוצים להשבית את השמירה האוטומטית במטמון עבור חלק מהישויות או כולן. אתם יכולים לשלוט בהתנהגות של המטמונים על ידי הגדרת פונקציות מדיניות. יש פונקציית מדיניות למטמון בתוך התהליך, שמוגדרת באמצעות
ועוד אחד ל-memcache, שמוגדר באמצעות
כל פונקציית מדיניות מקבלת מפתח ומחזירה תוצאה בוליאנית.
אם הפונקציה מחזירה False, הישות שמזוהה על ידי המפתח לא תינשמר במטמון המתאים.
לדוגמה, כדי לעקוף את המטמון בתהליך עבור כל הישויות Account, אפשר לכתוב
(אבל בהמשך נסביר איך לעשות את זה בצורה קלה יותר).
כדי לחסוך זמן, אפשר להעביר את הערכים True או False
במקום פונקציה שתמיד מחזירה את אותו ערך.
כברירת מחדל, המדיניות שומרת במטמון את כל הישויות.
יש גם פונקציית מדיניות של Datastore שקובעת אילו ישויות נכתבות ב-Datastore עצמו:
הפונקציה הזו פועלת כמו פונקציות המדיניות של מטמון בהקשר ו-memcache:
אם פונקציית המדיניות של Datastore מחזירה False
עבור מפתח נתון, הישות התואמת לא תיכתב ל-Datastore.
(יכול להיות שהנתונים ייכתבו למטמון בתהליך או ל-memcache
אם פונקציות המדיניות שלהם מאפשרות זאת).
האפשרות הזו שימושית במקרים שבהם יש לכם נתונים דמויי ישויות שאתם רוצים לשמור במטמון, אבל לא צריך לאחסן ב-Datastore.
בדומה למדיניות בנושא מטמון, אפשר להעביר True או
False במקום פונקציה שתמיד מחזירה את אותו ערך.
Memcache מפוג תוקף של פריטים באופן אוטומטי כשיש עומס על הזיכרון. אפשר להגדיר פונקציית מדיניות של פסק זמן ב-Memcache כדי לקבוע את משך החיים המקסימלי של ישות במטמון:
הפונקציה הזו נקראת עם ארגומנט של מפתח, והיא צריכה להחזיר מספר שלם שמציין את משך החיים המקסימלי בשניות. הערך 0 או None מציין משך חיים בלתי מוגבל (כל עוד יש מספיק זיכרון בשרת memcache).
לנוחותכם, אתם יכולים פשוט להעביר קבוע מספרי
במקום פונקציה שתמיד מחזירה את אותו ערך.
מידע נוסף על פסק זמן זמין במסמכי התיעוד של memcache.
הקשר חדש מתחיל עם מטמון ריק של נתונים בתהליך.
פונקציות המדיניות הן גמישות מאוד, אבל בפועל רוב כללי המדיניות הם פשוטים. לדוגמה,
- לא לשמור במטמון ישויות ששייכות למחלקה ספציפית של מודל.
- מגדירים את הזמן הקצוב לתפוגה של memcache לישויות במחלקת המודל הזו ל-30 שניות.
- אין צורך לכתוב ישויות בסוג המודל הזה ב-Datastore.
כדי לחסוך לכם את העבודה של כתיבה ועדכון מתמשך של פונקציות מדיניות פשוטות (או גרוע מכך, ביטול המדיניות לכל פעולה באמצעות אפשרויות הקשר), פונקציות מדיניות ברירת המחדל מקבלות את מחלקת המודל מהמפתח שמועבר אליהן, ואז מחפשות במחלקת המודל משתני מחלקה ספציפיים:
| משתנה מחלקה | סוג | תיאור |
|---|---|---|
_use_cache | bool | המדיניות הזו קובעת אם לאחסן ישויות במטמון בתוך התהליך, ועוקפת את מדיניות ברירת המחדל של המטמון בתוך התהליך. |
_use_memcache | bool | מציינת אם לשמור ישויות ב-memcache. המדיניות הזו מבטלת את מדיניות ברירת המחדל של memcache. |
_use_datastore | bool | מציין אם לאחסן ישויות במאגר הנתונים. ההגדרה הזו מבטלת את מדיניות ברירת המחדל של מאגר הנתונים. |
_memcache_timeout | int | משך החיים המקסימלי של ישויות ב-Memcache. הערך הזה מבטל את מדיניות ברירת המחדל של זמן קצוב לתפוגה של Memcache. |
הערה:
זוהי תכונה של פונקציית מדיניות ברירת המחדל לכל מדיניות.
אם מציינים פונקציית מדיניות משלכם, אבל רוצים גם לחזור למדיניות ברירת המחדל, צריך לקרוא לפונקציות של מדיניות ברירת המחדל באופן מפורש כשיטות סטטיות של המחלקה Context:
default_cache_policy(key)default_memcache_policy(key)default_datastore_policy(key)default_memcache_timeout_policy(key)