در دنیای نرمافزارهای مدرن، سرعت پاسخدهی و مقیاسپذیری سیستمها حیاتی است. کاربران انتظار دارند هر درخواستشان در چند میلیثانیه پاسخ داده شود، اما بسیاری از عملیاتها – مانند خواندن داده از پایگاه داده یا فراخوانی APIهای خارجی – ذاتاً کند هستند. اینجاست که Cache یا «حافظه نهان» وارد عمل میشود.
Cache چیست؟
Cache لایهای از حافظه است که دادههای پرمصرف را بهصورت موقت نگهداری میکند تا در درخواستهای بعدی بدون نیاز به پردازش مجدد یا مراجعه به دیتابیس، سریعتر پاسخ داده شوند. معمولاً کش در حافظه (RAM) نگهداری میشود و سرعت دسترسی آن چندین برابر سریعتر از پایگاه دادههای سنتی است.
چرا کش اهمیت دارد؟
- بهبود Performance: دسترسی به حافظه RAM بهطور متوسط ۱۰۰ تا ۱۰۰۰ برابر سریعتر از خواندن از دیسک یا دیتابیس است.
- کاهش بار روی دیتابیس: درخواستهای تکراری از کش پاسخ داده میشوند و فشار روی SQL Server یا Oracle کاهش مییابد.
- افزایش مقیاسپذیری (Scalability): کش باعث میشود اپلیکیشن بتواند با منابع ثابت، تعداد کاربران بیشتری را پاسخ دهد.
- بهبود تجربه کاربر (UX): زمان بارگذاری کمتر = رضایت بیشتر.
- کاهش هزینه: سرورهای کمتر، کوئریهای کمتر، مصرف منابع پایینتر.
انواع کش در سطح اپلیکیشن
در معماریهای مختلف، کش میتواند در سطوح متفاوتی پیادهسازی شود:
- In-Memory Cache: دادهها در حافظه همان سرور نگهداری میشوند (مثل
MemoryCacheدر .NET). - Distributed Cache: دادهها در حافظه اشتراکی (مانند
RedisیاMemcached) بین چند سرور بهاشتراک گذاشته میشوند. - Response Cache: ذخیرهسازی خروجی نهایی API برای جلوگیری از پردازش مجدد کنترلرها.
- Client-Side Cache: کش در مرورگر یا اپ موبایل برای دادههای ثابت (مثلاً لیست زبانها یا تنظیمات).
تکنولوژیهای پرکاربرد برای ذخیرهسازی موقت (Cache) اطلاعات
| تکنولوژی | ویژگیها | کاربرد |
|---|---|---|
| MemoryCache (.NET) | درونفرایندی، سریع، ساده | وباپهای کوچک و تکسرور |
| Redis | Distributed، پایدار، پشتیبانی از Pub/Sub و TTL | Microservices، Cloud، APIهای پرترافیک |
| Memcached | Distributed، سبک، بدون persistence | سیستمهای موقتی یا Real-time analytics |
| Nginx Cache | Reverse Proxy Caching | API Gatewayها و وبسرورها |
| Azure Cache for Redis | نسخه Cloud Redis با SLA بالا | سرویسهای Enterprise |
مثال: سیستم فروش آنلاین
فرض کنید یک فروشگاه آنلاین دارید که در هر ثانیه صدها کاربر محصولات را مشاهده میکنند. اگر هر بار برای گرفتن موجودی یا قیمت از دیتابیس استفاده شود، فشار زیادی به SQL Server وارد میشود. اما اگر نتایج کوئریهای پرکاربرد (مثلاً «محصولات پرفروش امروز») را در Redis برای ۶۰ ثانیه کش کنیم، میتوانیم با همان منابع، چند برابر درخواست را پاسخ دهیم — و کاربر همچنان دادههای بهروز دریافت میکند.
using Microsoft.Extensions.Caching.Memory;
public class ProductService
{
private readonly IMemoryCache _cache;
private readonly IProductRepository _repo;
public ProductService(IMemoryCache cache, IProductRepository repo)
{
_cache = cache;
_repo = repo;
}
public async Task<List<Product>> GetTopProductsAsync()
{
return await _cache.GetOrCreateAsync("top-products", async entry =>
{
entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(1);
return await _repo.GetTopProductsAsync();
});
}
}
نتیجهگیری
کش یکی از پایههای بهینهسازی در اپلیکیشنهای امروزی است. در سیستمهای بزرگ، بدون کش تقریباً غیرممکن است به عملکرد مناسب برسیم. از MemoryCache در پروژههای ساده گرفته تا Redis Cluster در معماریهای میکروسرویسی، هدف یکی است: کاهش تأخیر، افزایش سرعت، و بهبود تجربه کاربر.
در مقاله بعدی، به سراغ الگوی Cache Aside Pattern خواهیم رفت تا ببینیم چگونه میتوان دادهها را بین کش و دیتابیس بهصورت هماهنگ نگه داشت.