المقدمة
التخزين المؤقت (Caching) هو تقنية مهمة جدا لتحسين أداء التطبيقات، خصوصًا في تطبيقات الويب التي تتطلب استرجاع البيانات بشكل سريع وفعال. باختصار، Caching هو عملية تخزين البيانات مؤقتًا في الذاكرة بحيث يمكن الوصول إليها بسرعة في المستقبل بدون الحاجة لاسترجاعها من المصدر الأصلي (زي قاعدة البيانات أو خدمة خارجية). باستخدام Caching، يمكن تحسين أداء التطبيق بشكل كبير وتقليل وقت الاستجابة، مما يعزز تجربة المستخدم.
ما هو Caching؟
التخزين المؤقت يعني تخزين البيانات في الذاكرة لفترة قصيرة بحيث يمكن الوصول إليها بسرعة عند الحاجة مرة تانية. لو في حاجة لقراءة نفس البيانات أكثر من مرة، عادةً ما يكون الوصول إليها من الذاكرة أسرع بكتير من استرجاعها من قاعدة بيانات أو مصدر خارجي. في .NET، فيه أكثر من طريقة لتطبيق التخزين المؤقت، منها MemoryCache و DistributedCache.
أنواع Caching في .NET
في .NET، عندك خيارين أساسيين للتخزين المؤقت:
MemoryCache
هو عبارة عن تخزين مؤقت في الذاكرة المحلية. يتم استخدامه في التطبيقات اللي شغالة على جهاز واحد. البيانات المخزنة في الذاكرة بتكون موجودة فقط في نفس الجهاز أو الخادم.
DistributedCache
بيتم استخدامه في التطبيقات التي تحتاج إلى تخزين البيانات بشكل موزع على أكتر من خادم. ده مفيد جدًا لو كنت شغال في بيئة تستخدم أكثر من خادم أو في بيئة سحابية (مثل Azure أو AWS).
كيفية إضافة Caching في .NET
1. إضافة خدمة Caching
أول حاجة لازم تضيف خدمة التخزين المؤقت في الـ Startup.cs. في حالة استخدام MemoryCache، هتضيفها كده:
public void ConfigureServices(IServiceCollection services) {
// إضافة خدمة MemoryCache
services.AddMemoryCache();
}
أما لو كنت بتستخدم DistributedCache (لتخزين البيانات بشكل موزع)، هتستخدم الكود ده:
public void ConfigureServices(IServiceCollection services) {
// إضافة خدمة DistributedCache
services.AddDistributedMemoryCache();
}
ده هيخلي التطبيق جاهز لاستخدام التخزين المؤقت.
2. تخزين البيانات في Cache
دلوقتي بعد ما ضيفنا خدمة الـ Caching، هنستخدمها لتخزين البيانات في الذاكرة. في MemoryCache، بنقدر نستخدم GetOrCreate لتخزين واسترجاع البيانات.
private readonly IMemoryCache _cache;
public MyController(IMemoryCache cache) {
_cache = cache;
}
public IActionResult GetData() {
var value = _cache.GetOrCreate("myKey", entry => {
// تحديد وقت انتهاء الصلاحية للبيانات المخزنة
entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(5);
return "Data from cache!";
});
return Ok(value);
}
الشرح:
هنا احنا بنستخدم GetOrCreate للبحث عن القيمة المخزنة في الذاكرة تحت المفتاح myKey.
إذا كانت القيمة موجودة، هيتم إرجاعها مباشرة من الذاكرة.
إذا كانت القيمة مش موجودة، هيتم تنفيذ الكود اللي جوا الـ entry لتوليد القيمة (زي استعلام قاعدة البيانات، أو حسابات معينة)، وبعد كده تخزينها في الذاكرة.
entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(5) بيحدد مدة صلاحية البيانات المخزنة. هنا بنخلي البيانات تنتهي بعد 5 دقايق.
3. استخدام DistributedCache
في حالة استخدام DistributedCache، الطريقة بتكون مشابهة لكن بنستخدم تخزين مؤقت موزع. مثلا في حالة تطبيق يعمل على أكثر من خادم، هنستخدم الكود التالي:
private readonly IDistributedCache _distributedCache;
public MyController(IDistributedCache distributedCache) {
_distributedCache = distributedCache;
}
public async Task<IActionResult> GetData() {
var value = await _distributedCache.GetStringAsync("myKey");
if (value == null) {
value = "Data from cache!";
await _distributedCache.SetStringAsync("myKey", value, new DistributedCacheEntryOptions {
AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(5)
});
}
return Ok(value);
}
هنا بنستخدم DistributedCache، والطريقة مشابهة لـ MemoryCache لكن بيتم تخزين البيانات بشكل موزع على عدة خوادم.
فوائد Caching في .NET
التخزين المؤقت في .NET له العديد من الفوائد التي تساهم في تحسين أداء التطبيق بشكل كبير. من أبرز الفوائد:
1. تحسين السرعة:
من أهم فوائد الـ Caching هي تحسين سرعة الوصول للبيانات. البيانات المخزنة في الذاكرة يمكن الوصول إليها بسرعة كبيرة مقارنةً بقاعدة البيانات. لما تحتاج تسترجع نفس البيانات بشكل متكرر، الـ Cache هيوفر لك وقت كبير في عملية الاسترجاع.
مثال: لو عندك تطبيق بيعتمد على استعلامات قاعدة بيانات معقدة، باستخدام الـ Cache، تقدر تخزن النتائج في الذاكرة بعد أول استعلام، وبالتالي مع كل استعلام تالي هتوفر الوقت بدل من إعادة حساب الاستعلامات أو الرجوع لقاعدة البيانات.
2. تقليل الحمل على الخوادم وقواعد البيانات:
التخزين المؤقت بيساعد في تقليل عدد الطلبات التي بتتوجه إلى الخوادم أو قواعد البيانات. إذا كانت البيانات مخزنة في الذاكرة، التطبيق مش هيلجأ للاستعلام عن البيانات في كل مرة، وبالتالي بيساهم في تقليل الضغط على الخوادم وتحسين الأداء العام.
3. تقليل التكلفة:
لو كنت بتستخدم خدمات سحابية أو قاعدة بيانات خارجية، كل استعلام قاعدة بيانات بيكلفك جزء من المال (خاصة لو كان عندك حجم استعلامات كبير). باستخدام التخزين المؤقت، بتقلل عدد الاستعلامات وبالتالي بتقلل التكلفة المرتبطة بها.
4. تحسين تجربة المستخدم:
من خلال تقليل زمن الاستجابة (Response Time) وتحسين سرعة الوصول للبيانات، تجربة المستخدم هتتحسن بشكل كبير. المستخدمين هيلقوا التطبيق أسرع في الاستجابة لأوامرهم.
5. دعم قابلية التوسع:
التخزين المؤقت الموزع (Distributed Caching) بيساعد في توسيع التطبيقات على عدة خوادم. البيانات المخزنة بتكون متاحة لجميع الخوادم الموجودة في البنية التحتية، مما يدعم قابلية التوسع ويضمن استمرارية الأداء العالي.
أفضل الممارسات في استخدام Caching
تحديد وقت صلاحية البيانات بشكل مناسب: لازم تحدد فترة صلاحية البيانات المخزنة في الـ Cache بعناية. البيانات اللي بتحتاج تكون محدثة بشكل مستمر لازم تكون صلاحيتها قصيرة، بينما البيانات الثابتة أو اللي مش هتتغير كثير ممكن تحتفظ بها لفترات أطول.
التخزين المؤقت بحذر: مش كل البيانات تستحق أن يتم تخزينها في الـ Cache. البيانات الكبيرة أو الحساسة لازم تبقى بعيدة عن الـ Cache عشان متعرضش البيانات للخطر.
استخدام طرق تحقق من التحديثات (Cache Invalidation): لما تكون البيانات في الـ Cache قديمة أو تم تحديثها، لازم يكون في طريقة لإبطال (Invalidate) الـ Cache عشان تضمن أنك مش هتعرض بيانات غير محدثة.
مراقبة الـ Cache: يجب مراقبة استخدام الـ Cache بشكل دوري. لازم تتأكد أن البيانات المخزنة فعلاً بتساهم في تحسين الأداء وليست مجرد استخدام غير فعال للذاكرة.
في الختام
التخزين المؤقت في .NET هو أداة قوية لتحسين أداء التطبيقات. من خلال تخزين البيانات في الذاكرة بدلاً من استرجاعها من قواعد البيانات أو مصادر أخرى بشكل مستمر، يمكنك تقليل زمن الاستجابة، تحسين أداء التطبيق، وتقليل الضغط على الخوادم. لازم يكون في إدارة جيدة لعملية التخزين المؤقت عشان تضمن أنك بتخزن البيانات الصحيحة وبالطريقة الصحيحة لتحقيق أفضل استفادة ممكنة.
Discussion