🎯 ءCache فقط Redis گذاشتن جلوی Database نیست!
یکی از سؤالهای جالبی که در مصاحبههای Software Engineering ممکنه ازت بپرسن اینه:
«چه استراتژیهایی برای Caching میشناسی؟»
خیلیها سریع جواب میدن:
«Cache Aside.»
و تمام.
اما وقتی وارد سیستمهای واقعی میشیم، میبینیم که چند مدل مختلف برای مدیریت ارتباط بین Application، Cache و Database داریم.
بریم سراغ مهمترینها 👇
1️⃣ Cache-Aside / Lazy Loading
احتمالاً رایجترین الگویی که در پروژهها میبینید. Application ابتدا Cache را بررسی میکند.
مثلاً:
GET Product:123
اگر محصول داخل Redis باشد، همان را برمیگردانیم.
اگر نباشد:
Redis → Miss
↓
SQL Server
↓
Redis.Set(Product:123)
↓
Response
مزیت اصلی:
فقط چیزی را Cache میکنیم که واقعاً درخواست شده است.
برای Read-heavy workloadها و دادههایی مثل Product، User Profile و Catalog معمولاً انتخاب بسیار خوبی است.
📌اما یک نکته مهم دارد:
ءCache-Aside خودش Consistency بین Cache و Database را تضمین نمیکند.
معمولاً هنگام Update، Database را تغییر میدهیم و Entry مربوطه را Invalidate میکنیم تا درخواست بعدی دوباره آن را Load کند.
2️⃣ Read-Through
از بیرون شبیه Cache-Aside است، اما یک تفاوت مهم دارد.
در Cache-Aside:
ءApplication مسئول Fetch کردن از Database است.
در Read-Through:
ءCache Layer مسئول Fetch کردن Data Source است.
یعنی Application فقط با Cache کار میکند:
Application
↓
Cache
↓
Miss
↓
Data Store
این مدل میتواند Application Code را سادهتر کند، اما نیازمند Cache یا Infrastructureای است که بتواند این Fetch Logic را مدیریت کند.
3️⃣ Write-Through
اینجا داستان از سمت Write شروع میشود.
وقتی Data تغییر میکند، Cache و Primary Store باید در همان مسیر Write بهروز شوند.
هدف این است که بعد از یک Write موفق، Cache هم نسخه بهروز Data را داشته باشد.
مزیت؟
احتمال Cache Miss بعد از Write کمتر میشود و Readهای بعدی میتوانند سریع باشند.
اما یک مشکل دارد:
ممکن است Dataای را وارد Cache کنیم که اصلاً کسی قرار نیست آن را بخواند.
در نتیجه:
ءMemory و Cache Churn بیشتری داریم.
برای همین Write-Through معمولاً بهتنهایی استفاده نمیشود و میتواند در کنار Lazy/Cache-Aside قرار بگیرد.
4️⃣ Write-Behind / Write-Back
اینجا قضیه جدیتر میشود. Application ابتدا Data را در Cache مینویسد و Database در ادامه و بهصورت Asynchronous بهروزرسانی میشود.
Application
↓
Redis
↓
Async Worker
↓
Database
مثلاً یک سیستم با حجم بسیار زیاد:
Like Counter
View Counter
Analytics Event
ممکن است نخواهد برای هر Write منتظر Database بماند.
پس:
100,000 Writes
↓
Redis
↓
Batch
↓
Database
این مدل میتواند Write Throughput را بالا ببرد و فشار روی Database را کاهش دهد.
اما یک Trade-off بسیار مهم دارد: Durability.
اگر Data هنوز به Database نرسیده باشد و Cache از دست برود، ممکن است Data هم از دست برود.
بنابراین برای Dataهایی که از دست رفتنشان قابل قبول نیست، باید بسیار محتاط بود.
5️⃣ Write-Around
یک Pattern کمتر دیدهشده: Write مستقیماً به Database میرود و Cache درگیر Write نمیشود.
Write
↓
Database
Read
↓
Cache
↓
Miss
↓
Database
↓
Cache
برای دادههایی که زیاد Write میشوند ولی بلافاصله Read نمیشوند، میتواند مفید باشد.
چون مجبور نیستیم هر Dataای که نوشته میشود را وارد Cache کنیم.