🚀 کشینگ در ASP.NET Core (قسمت ۳):
الگوی حرفهای Cache-Aside
در قسمت قبل، با IMemoryCache آشنا شدیم. عالی بود، ولی یه مشکل بزرگ داشت: اگه چند تا سرور داشته باشیم، کش بینشون به اشتراک گذاشته نمیشه.
امروز میخوایم با الگوی Cache-Aside و اینترفیس IDistributedCache آشنا بشیم تا این مشکل رو حل کنیم و کدهامون رو برای کشینگ، خیلی تمیزتر و قابل استفاده مجدد کنیم.
1️⃣ الگوی Cache-Aside چیست؟ 🤓
این الگو، رایجترین و استانداردترین استراتژی برای کار با کشه. منطقش خیلی سادهست:
• اول کش رو چک کن: برنامه شما اول به کش نگاه میکنه.
• اگه تو کش بود، برش گردون: اگه داده اونجا بود (Cache Hit)، کار تمومه.
• اگه نبود، برو سراغ منبع اصلی: اگه داده تو کش نبود (Cache Miss)، برو از منبع اصلی (مثل دیتابیس) بخونش.
• کش رو آپدیت کن و برگردون: دادهای که از منبع اصلی گرفتی رو تو کش ذخیره کن تا برای دفعه بعد آماده باشه و بعد به کاربر برگردون.
2️⃣ ساخت یک ابزار حرفهای: متد توسعه GetOrCreateAsync 🛠
به جای اینکه این منطق ۴ مرحلهای رو هر بار تکرار کنیم، میتونیم یه متد توسعه (Extension Method) خفن برای IDistributedCache بنویسیم که این کار رو برامون انجام بده.
public static class DistributedCacheExtensions
{
// یه زمان انقضای پیشفرض تعریف میکنیم
public static DistributedCacheEntryOptions DefaultExpiration => new()
{
AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(2)
};
public static async Task<T> GetOrCreateAsync<T>(
this IDistributedCache cache,
string key,
Func<Task<T>> factory, // تابعی که قراره داده رو از منبع اصلی بگیره
DistributedCacheEntryOptions? options = null)
{
var cachedData = await cache.GetStringAsync(key);
if (cachedData is not null)
{
// اگه داده تو کش بود، از JSON برش میگردونیم
return JsonSerializer.Deserialize<T>(cachedData);
}
// اگه نبود، تابع factory رو اجرا میکنیم تا از منبع اصلی بگیره
var data = await factory();
// داده جدید رو به صورت JSON در کش ذخیره میکنیم
await cache.SetStringAsync(
key,
JsonSerializer.Serialize(data),
options ?? DefaultExpiration);
return data;
}
}
3️⃣ نحوه استفاده از ابزار جدید ✨
حالا ببینید اون کد شلوغ قبلی، با این متد توسعه چقدر تمیز و خوانا میشه:
app.MapGet("products/{id}",
async (int id, IDistributedCache cache, AppDbContext context) =>
{
// فقط کافیه متد خودمون رو صدا بزنیم!
var product = await cache.GetOrCreateAsync($"products-{id}", async () =>
{
// این تابع فقط زمانی اجرا میشه که داده تو کش نباشه
return await context.Products.FindAsync(id);
});
return Results.Ok(product);
});💡نکته: برای اینکه این کد کار کنه، باید اول سرویس IDistributedCache رو در Program.cs ثبت کنیم:
builder.Services.AddDistributedMemoryCache();
🔖 هشتگها:
#ASPNETCore #Caching