From 2bcc41cbb56162ab1374d7658c00a288b31bd16b Mon Sep 17 00:00:00 2001
From: Roy Mayan <>
Date: Mon, 16 Jun 2025 21:55:55 +0300
Subject: [PATCH] Translating - finished cache
---
README-he.md | 148 +++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 143 insertions(+), 5 deletions(-)
diff --git a/README-he.md b/README-he.md
index a101d449..4c85cf9f 100644
--- a/README-he.md
+++ b/README-he.md
@@ -1647,7 +1647,6 @@ Workers בשכבת האפליקציה מסייעים גם [לא-סינכרוני
במקום לשמור תוצאה של שאילתה, נחשוב על הנתונים כמו על "אובייקט" בקוד.
האפליקציה שולפת את המידע מה-DB ומרכיבה ממנו מופע שמתאר אותו תוך שימוש ב-class כלשהו:
-
- יש להסיר את האובייקט מה-cache אם אחד מהשדות שלו השתנה
- מאפשר עיבוד אסינכרוני: תהליכים ברקע יכולים להרכיב אובייקטים על ידי הדבר האחרון שנמצא ב-cache
@@ -1655,9 +1654,148 @@ Workers בשכבת האפליקציה מסייעים גם [לא-סינכרוני
הצעות לדברים שכדאי לבצע להם cache:
-* User sessions
-* Fully rendered web pages
-* Activity streams
-* User graph data
+- User sessions
+- Fully rendered web pages
+- Activity streams
+- User graph data
+
+### מתי לעדכן את ה-cache?
+
+כיוון שאפשר לאחסן רק כמות מוגבלת של מידע ב-cache, יש לבחור באסטרטגיית עדכון ופינוי המקום ב-cache שמתאימה ביותר עבור המערכת.
+
+#### אסטרטגיית Cache-Aside
+
+
+
+
+ Source: From cache to in-memory data grid
+
+
+האפליקציה אחראית לבצע קריאה וכתיבה מול האחסון. ה-cache לא מדבר עם האחסון ישירות. האפליקציה עושה את הדברים הבאים:
+
+ - חיפוש הרשומה ב-cache, מה שמוביל ל-cache miss
+ - טוענים את הרשומה מהאחסון
+ - שומרים את התוצאה ב-cache
+ - מחזירים את הרשומה ללקוח
+
+
+```python
+def get_user(self, user_id):
+ user = cache.get("user.{0}", user_id)
+ if user is None:
+ user = db.query("SELECT * FROM users WHERE user_id = {0}", user_id)
+ if user is not None:
+ key = "user.{0}".format(user_id)
+ cache.set(key, json.dumps(user))
+ return user
+```
+למשל [Memcached](https://memcached.org/) יכול להיות בשימוש בקטע קוד מהסוג הזה, האפליקציה היא זו שקובעת מתי לקרוא ולכתוב ל-cache.
+אחרי שהפריט נכתב ל-cache, כל קריאה חוזרת אליו מהירה במיוחד. אסטרטגייה זו נקראת גם lazy loading. רק מידע שנעשתה אליו גישה נכנס ל-cache, מה שמונע שמירה של הרבה דאטא שאין בו שימוש.
+
+##### חסרונות: cache-aside
+
+
+ - כל cache miss עולה לנו ב-3 שלבים, מה שיכול לגרום לעיכוב משמעותי.
+ - הדאטא יכול להתיישן אם הוא מתעדכן ב-DB. הרשומה ב-RAM כבר לא רלוונטית. אפשר לקבוע TTL קצר או לעבור לאסטרטגיה של write-through.
+ - כאשר שרת ה-cache קורס, הוא מוחלף באחד חדש שעולה ריק מאפס, מה שגורם ל-latency גבוה.
+
+
+#### אסטרטגיית Write-Through
+
+
+
+
+ Source: Scalability, availability, stability, patterns
+
+
+האפליקציה מתייחסת אל ה-cache כאחסון המרכזי, מבצעת קריאות וכתיבות מולו, כאשר ה-cache אחרי לבצע את הקריאות והכתיבות מול ה-DB:
+
+
+ - האפליקציה מוסיפה או מעדכנת רשומה ב-cache
+ - ה-cache מסנכרן כל כתיבה ל-DB
+ - הפעולה חוזרת למשתמש
+
+
+Application code:
+
+```python
+set_user(12345, {"foo":"bar"})
+```
+
+Cache code:
+
+```python
+def set_user(user_id, values):
+ user = db.query("UPDATE Users WHERE id = {0}", user_id, values)
+ cache.set(user_id, user)
+```
+
+אסטרטגיה זו איטית יותר בשל ביצוע ה-write (שתי כתיבות במקום אחת), אבל קריאות שיקרו בהמשך של הדאטא שזה עתה נכתב יהיו מהירות. המשתמשים לרוב יותר סבלניים לגבי שיהוי כאשר מעדכנים את הדאטא לעומת קריאה שלו. הדאטא ב-cache תמיד עדכני.
+
+##### חסרונות: write through
+
+
+ - כאשר עולה node חדש של ה-cache הוא לא יכיר אף רשומה עד שהיא לא תתעדכן ב-DB, המערכת צריכה קודם לבצע עדכונים לאותם הערכים. שילוב של cache-aside עם write-through יכול לצמצם את הבעיה - אם אין ערך, האפליקציה טוענת מה-DB ושומרת ב-cache, ואז העדכון נכנס גם ל-cache וגם ל-DB.
+ - חלק גדול מהנתונים שנכתבים לעולם לא ייקראו, כל כתיבה נשמרת ל-cache ותופסת RAM יקר בלי שבהכרח יש בה שימוש. אפשר למנוע את בזבוז הזיכרון באמצעות TTL על ערכים שאינם נקראים. הערכים שעדיין "חמים" יתעדכנו מחדש ב-TTL בכל קריאה או כתיבה.
+
+
+#### אסטרטגיית Write-Behind/Back
+
+
+
+
+ Source: Scalability, availability, stability, patterns
+
+
+האפליקציה מבצעת את הפעולות הבאות:
+
+ - הוספה או עדכון של רשומה ב-cache.
+ - כתיבת הרשומה באופן אסינכרוני ל-DB, כך זמן הכתיבה שנתפס בעיני המשתמש קצר מאוד, מפני שהחלק האיטי (לדיסק) נעשה ברקע.
+
+
+##### חסרונות: write-behind
+
+
+ - יכול להיות אובדן מידע אם ה-cache נופל לפני שהכתיבה האסינכרונית ל-DB הסתיימה, ואז הרשומות נעלמו לנצח.
+ - יותר מורכב לממש write-behind מאז לממש את האסטרטגיות הקודמות כמו cache-aside או write-through.
+
+
+#### אסטרטגיית Refresh-Ahead
+
+
+
+
+ Source: From cache to in-memory data grid
+
+
+אפשר לקנפג את ה-cache כך שהוא ירענן כל פריט שניגשו אליו לאחרונה לפני שתפוג תקופת ה-TTL שלו (יבצע fetch מול ה-DB).
+
+אם המערכת יודעת לחזות בצורה טובה אילו פריטים יבוקשו שוב בקרוב, נקבל latency נמוך יותר משיטות read-through רגילות: המשתמש יקבל תשובה מ-cache שכבר עבר עדכון ברקע (ואין cache miss).
+
+##### חסרונות: refresh-ahead
+
+
+ - חיזוי לא מדויק של פריטים שיידרשו בעתיד יכול לגרום לרענון מיותר, ובזבוז של RAM וחיבורים ל-DB, מה שעלול לגרום לתוצאות איטיות יותר מאשר בלי לבצע refresh-ahead.
+
+
+### חסרונות: cache
+
+
+ - חייבים לשמר עקביות בין ה-cache ומקור המידע האמיתי (ה-DB) באמצעות cache invalidation, כללים הקובעים מתי מוחקים או מרעננים ערכים ב-cache.
+ - cache invalidation הוא אתגר לא פשוט, יש מורכבות נוספת להבנה מתי בדיוק ערך ב-cache הוא כבר לא עדכני.
+ - נדרשים לבצע שינויים בקוד ובתשתית להוספת רכיבים כמו Redis או Memcached.
+
+
+### מקורות וקריאה נוספת
+
+- [From cache to in-memory data grid](http://www.slideshare.net/tmatyashovsky/from-cache-to-in-memory-data-grid-introduction-to-hazelcast)
+- [Scalable system design patterns](http://horicky.blogspot.com/2010/10/scalable-system-design-patterns.html)
+- [Introduction to architecting systems for scale](http://lethain.com/introduction-to-architecting-systems-for-scale/)
+- [Scalability, availability, stability, patterns](http://www.slideshare.net/jboner/scalability-availability-stability-patterns/)
+- [Scalability](https://web.archive.org/web/20230126233752/https://www.lecloud.net/post/9246290032/scalability-for-dummies-part-3-cache)
+- [AWS ElastiCache strategies](http://docs.aws.amazon.com/AmazonElastiCache/latest/UserGuide/Strategies.html)
+- [Wikipedia](https://en.wikipedia.org/wiki/Cache_(computing))
+
+