TGViewer
C# Geeks (.NET) C# Geeks (.NET) @csharpgeeks · 550 subscribers
Post #765 229
🧠 ءCaching فقط برای کم کردن Latency نیست؛ مشکل اصلی بعد از اضافه کردن Cache شروع می‌شود!
وقتی برای اولین بار Redis را وارد معماری می‌کنیم، معمولاً مسئله خیلی ساده به نظر می‌رسد:
«دیتای پرتکرار را از Database بخوان، داخل Redis بگذار و Requestهای بعدی را از Cache جواب بده.»

و واقعاً هم همین کار باعث کاهش Load روی Database و کاهش Latency می‌شود.
اما یک سؤال مهم وجود دارد:
❓ وقتی Data در Database تغییر کرد، Redis از کجا بفهمد که مقدار قبلی دیگر معتبر نیست؟
فرض کنید:
Database
Product:123
Price = 100

Redis
Product:123
Price = 100

حالا قیمت محصول تغییر می‌کند:
Database
Product:123
Price = 150

اما Redis هنوز دارد:
Redis
Product:123
Price = 100

اگر Cache Invalidation درست انجام نشود، کاربر ممکن است همچنان قیمت 100 را دریافت کند؛ در حالی که Source of Truth مقدار 150 را دارد.
اینجاست که مسئله واقعی Caching خودش را نشان می‌دهد:
🔥 Cache Invalidation
🔹 Cache-Aside Pattern
یکی از رایج‌ترین الگوها برای Cache کردن داده، Cache-Aside است.
در Read:
Request
↓
Redis
↓
Cache Hit?
┌───────┴───────┐
Yes No
↓ ↓
Return Database
↓
Update Redis
↓
Return

یعنی Application خودش مسئول مدیریت Cache است.
اگر Data در Cache وجود داشته باشد، همان مقدار استفاده می‌شود.
اگر وجود نداشته باشد، Application سراغ Database می‌رود و بعد مقدار خوانده‌شده را در Cache قرار می‌دهد.
اما مشکل اصلی در Update اتفاق می‌افتد.
معمولاً داریم:
Update Database
↓
Invalidate Cache

مثلاً:
await db.Products.UpdateAsync(product);

await redis.RemoveAsync($"product:{product.Id}");

ءRequest بعدی دوباره Data را از Database می‌خواند و Cache را با مقدار جدید Populate می‌کند.
تا اینجا همه‌چیز خوب به نظر می‌رسد...
اما یک Race Condition می‌تواند تمام این طراحی را خراب کند. 👇

⚠️ ءRace Condition در Cache

فرض کنید دو Request تقریباً همزمان اتفاق می‌افتند. Request A می‌خواهد قیمت را 150 کند. Request B تقریباً همزمان Data قدیمی را از Database می‌خواند.
ممکن است چیزی شبیه این اتفاق بیفتد:
Request A                 Request B

Update DB → 150

Read DB → 100
↓
Set Redis → 100

Delete Redis

حالا Database مقدار 150 دارد، اما بسته به ترتیب دقیق عملیات، Cache ممکن است دوباره با مقدار قدیمی Populate شود.
این یکی از دلایلی است که طراحی Cache در سیستم‌های Concurrent بسیار پیچیده‌تر از یک GET و SET ساده است.
🔐 پس فقط DEL کردن Redis کافی نیست؟
نه همیشه.
بسته به Requirement سیستم، ممکن است به تکنیک‌های دیگری نیاز داشته باشید:
🔹 Optimistic Locking
برای تشخیص اینکه Data در فاصله بین Read و Write تغییر کرده است.
🔹 Distributed Lock
در سناریوهایی که چند Instance نباید همزمان یک عملیات حساس را انجام دهند.
🔹 Versioning
برای اینکه بتوانیم تشخیص دهیم مقدار Cache مربوط به چه Versionی از Data است.
مثلاً:
Product
Version = 42
Price = 150

و Cache هم Version را نگه دارد.
اگر یک Update قدیمی با Version پایین‌تر بخواهد Cache را Update کند، می‌توان آن را نادیده گرفت.
🔹 Event-driven Cache Invalidation
به جای اینکه هر قسمت Application خودش مسئول Invalidate کردن Cache باشد، تغییرات Data را به صورت Event منتشر کنیم:
Database Update
↓
Domain / Integration Event
↓
Cache Invalidation Handler
↓
Redis DEL

🔹 TTL
و در نهایت TTL می‌تواند یک لایه محافظتی دیگر باشد.
⏳ اما یک اشتباه رایج:
ءTTL به‌تنهایی مشکل Consistency را حل نمی‌کند.
اگر:
TTL = 5 minutes

باشد، این یعنی Data قدیمی ممکن است تا ۵ دقیقه در Cache باقی بماند. TTL فقط می‌گوید:
«این Data بعد از این مدت دیگر معتبر نیست.»

اما نمی‌گوید:
«به محض تغییر Source of Truth، Cache هم فوراً معتبر بودنش را از دست بدهد.»

بنابراین اگر Requirement شما Strong Consistency است، نباید TTL را جایگزین Cache Invalidation بدانید.
⚖️ آیا همیشه Strong Consistency لازم داریم؟
اینجا باید از Business Requirement شروع کنیم، نه از تکنولوژی.
برای بعضی Dataها چند ثانیه اختلاف کاملاً قابل قبول است:
Product View Count
Analytics
Recommendation
Reporting Data

اگر View Count یک محصول برای چند ثانیه 10,521 و بعد 10,524 باشد، احتمالاً Business مشکلی ندارد.
در اینجا Eventual Consistency می‌تواند انتخاب کاملاً منطقی‌ای باشد.
More from @csharpgeeks
  1. Sep 22, 2026یه مدتی قراره از دنیای NET. فاصله بگیرم، چون وقتشه برم سربازی. راستش نمیدونم این مدت رو چج…
  2. Sep 20, 2026🔥 حالا مشکل اصلی: Alert Storm فرض کن Database از دسترس خارج شده. ۱۰۰ Pod داری. هر Pod می‌…
  3. Sep 20, 2026🚨 طراحی سیستم Monitoring و Alerting در یک سیستم بزرگ فرض کن ساعت ۳ صبح است. سیستم شما با…
  4. Sep 19, 2026#Engineering_Leadership تصمیم نگرفتن هم یک تصمیم است یه چیز عجیب توی تیم‌های مهندسی: گاهی…
  5. Sep 19, 2026☑ چک‌لیست آماده‌سازی تیم، فرایندها و زیرساخت برای توسعه با AI توجه: هیچ چک‌لیستی جهان‌شمول…
  6. Sep 19, 2026📌پایان یک انتظار طولانی: اعتبارسنجی ناهمگام (Async Validation) در NET 11.
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →