Distributed Cache Or In-Memory Cache

Sea Bass

New member
Distributed Cache Or In-Memory Cache

שלום לכולם,
אשמח לשמוע את דעתכם על שימוש שאני חושב לבצע ב Cache.
אני כותב Service מסויים שהוא stateless, זתומרת שאני יכול להרים מספרים Instances שלו וכל אחד קורא מ DB ובמבצע כל מיני פעולות.
כל Instance פורק מ queue מסויים הודעות.
הService הזה עושה גם שימוש ב Redis בתור Distributed Cache.
אחד המדברים שהסביס הזה עושה הוא מאזין לאיזה תור ורושם מידע ל DB ושם אותו ב cache נניח לשעה.
כל פניה למידע נבדקת קודם ב cache ואם הוא ריק אז פונים ל DB (ושמורים ל cache).
עכשיו יש לי מידע שכמעט אף פעם לא משתנה. נניח location של עובד במשרד. זה סוג מידע שיכול להשתנות פעם בחודש (לכל המשרד).
זהו סוג מידע שאני קורא המון המון המון פעמים. כל פניה כזאת ל REDIS זה בעצם פעולת IO שאם המידע הזה היה שמור לי ב memory בתוך השרת זה היה הכי יעיל מבחינתי.היה חוסך לי פניות.
אז חשבתי להתשמש ב Redis pub/sub. כל ה Instances מאזינים ל channel מסויים. אחד מהם מקבל שינוי מידע דרך Queue, במקום לשמור ל Redis, המידע נשמר ל DB ואז נשלח הודעה דרך pub/sub וכל Instance שלמעלה ומאזין, פונה ל DB ושומר In-Memory.
אני מזכיר זהו מידע שיכול להשתנות בתדירות מאד נמוכה כמו החלפת שעון.
נגיד גם שכל Instance חדש שעולה שואב את המידע מה DB בזמן העלייה.

מה דעתכם? מה החסרונות? האם אני חושב על משהו לא טוב? האם הדרך לא טובה?

תודה רבה.
 

nocgod

New member
האם יש בעיית ביצועים בסיפור שלך?

כי אם אין, אני אשאל - למה אתה צריך cache?

לגבי השאלה המקורית שלך. הוספה של מנגנוני cache זה לא פשוט, אחד הדברים הקשים זה לדעת מתי לעשות invalidate ו evict ל cache.
בהנחה שיש לך בסיס נתונים, קאש מבוזר, קאש בזיכרון ואת כל זה אתה מסנכרן באמצעות pub/sub שאין לו הבטחת delivery at least once - אתה נראה לי מכניס את עצמך עמוק לתוך איזה בור עמוק.
א. למה לא להשתמש בבסיס נתונים שמבטיח עדכון לכל הרשומים לעיניין?
ב. למה לא להשתמש בActor model כדי לוודא שבקשות לאותו המידע ישורתו על ידי אותו Actor?
ג. אם אתה מסנכרן מידע באמצעות pub/sub אתה לא צריך את ה cache המבוזר לדעתי, אבל חייב לשים לב שמידע יכול להיות לא מסונכרן בין ה instances.

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

Sea Bass

New member
אז ככה

קודם כל תודה על התגובה.
אין לי כרגע בעיית ביצועים כי הסרביס לא פתוח לכל המערכת רק על חלק ממנה.
הבסיס נתונים של המערכת הזו היא SQL ולשם נרשמים כל הנתונים.
בנוגע לסעיף א' - לאיזה בסיס נתונים אתה מתכוון? יכול להיות שאני לא מכיר. בסיס נתונים שכל אחד נרשם עליו והוא מפיץ כל עדכון חדש?
אתה יכול לפרט יותר?
*אני ממש לא מתכוון להשץמש ב CACHE לוקאלי על המכונה ו CACHE מבוזר ביחד.
בנוגע לסעיף ב' - שמוש ב ACTOR (שאני מבתע עם AKKA בחלק מהמערכות) לא חשבתי שיעזור לי כי "הבעיה" שלי הייתה גישה ל DB בקצב גבוה למידע שכמעט ולא מתעדכן.
בנוגע לסעיף ג' - כפי שרשמתי אני לא מתכוון להשתמש ב CACHE מבוזר.

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

nocgod

New member
ככה?

א. עד כמה שאני זוכר firebase הוא שירות כזה, עוד דוגמא שמצאתי עכשיו https://pusher.com/tutorials/mongodb-change-streams
ב. אני פחות משתמש ב AKKA, יותר ב ORLEANS (בין החברות הגדולות שמשתמשת ב orleans ב production). לצורך הדוגמא יש כמה דיונים ב orleans על איך לבצע מצב של single write multi read.
https://github.com/dotnet/orleans/issues/3841
https://github.com/dotnet/orleans/issues/4062
אני בטוח שאפשר לתרגם את הקונספט הזה גם ל akka.

בסה"כ אם אני מבין נכון את הבעיה שלך נכון, יש לך כמה שירותים stateless שקוראים דברים, מכניסים ל DB. הבעיה שלך היא בעצם שיש קצב קריאה גבוה למידע שמשתנה מעט מאוד. אם הייתה לי בעיית ביצועים בקיראה, אני הייתי פותר את זה (אם אני נשאר בעולם stateless) באמצעות עבודה מול redis בלי pubsub ובלי in-memory cache. הייתי דואג להגדיר לו TTL נמוך יחסית. ככה גם נקודת ה revocation נמצאת במקום אחד בלבד, אתה לא יכול להגיע למצב שיש instace A שחושב שהמידע שונה משאר ה cluster. כמובן שאם הייתי רוצה לסבך את הגישה ל cache הייתי שם אותו כ fallback policy מהDB במקרה שזמני התשובה לא טובים.

לגבי האי-הסכמה, זאת זכותך המלאה לא להסכים, דעות שונות וזה. אני מאמין שהמערכת צריכה להשאר as simple as possible כל עוד היא נותנת את הדרישות הנחוצות ממנה. caching זה תהליך קשה בשאלה של למה לעשות cache מתי לעשות cache ומתי לעשות cache invalidation ומתי לעשות TTL כדי להבטיח שלא קרתה פאדיחה והלך לאיבוד איזה invalidation בדרך ואתה מחזיר stale data, טיפול ב cache poisoning ועוד מיליון ואחד בעיות שפגשתי ביום-יום שלי. בגלל זה כל פעם שאני רואה אנשים שמנסים להשתמש ב caching system כלשהי אני קודם כל מנסה להבין מה הביא אותם לחשוב שהם צריכים אם זה מלכתחילה והאם כל הפתרונות הפשוטים ביותר מוצו.
 

Sea Bass

New member
משהו אחד לא הבנתי

קודם כל תודה על התגובה.
לא הבנתי מהי נקודת revocation. אתה רושם:
"ככה גם נקודת ה revocation נמצאת במקום אחד בלבד"
הרי נניח שהגדרתי TTL נמוך וה ITEM בredis עף אחרי הזמן (TTL נגמר), מה קורה אז בנקודה הזאת בדיוק?
יש קוד שהולך ל DB ומביא את המידע ל REDIS בצורה אוטומית על ידי טריגר? או מחכים שתיהיה פניה לredis, רואים שהוא ריק ואז מעדכנים?

את זה לא הבנתי.
 

nocgod

New member
הכוונה בנקודת revocation

זה נקודה בקוד שבה אתה מחליט למחוק את הcache או לעדכן את הcache

לפעמים TTL הוא פרק זמן ארוך מידי ואז בקשות יכולות להתחיל לקבל מידע ישן עד שיפוג ה TTL.
בגלל זה מאוד רצוי שתעשה cache revocation או cache refresh אחרי ששמרת בהצלחה לDB, ובמקרה והבקשה ל redis לא הצליחה מאיזשהי סיבה וה cache לא נמחק/רוענן, אז לפחות יש לך TTL כדי לוודא שמידע ישן לא יושב יותר מידי זמן ב cache.

לגבי השאלה שלך של מה אמור לקרות אחרי TTL - מקבלים cache miss, הולכים ל DB מביאים ערך רענן ומעדכנים את ה cache מחדש

לגבי איך להביא את המידע ל redis - בכנות אני אגיד לא מכיר אם יש מנגנונים אוטומטיים שיעשו כזה כבר - אני גם מעדיף שלא יהיו, אני לא אוהב implicit side-effects כי אז יש הרבה magic שמעט מאוד אנשים מבינים. תהליך עדכון cache לרוב קורה כמו שהסברתי בפסקה הראשונה.

אם נחזור לדוגמא בשימוש עם virtual/actor model אתה בתחלס לא צריך cache כי ה actor/grain שלך הוא ה cache שלך
 
למעלה