كل البرمجيات لديها بيانات يتم جلبها من قاعدة البيانات، هنالك بيانات يتم جلبها بإستمرار، في البرمجيات الضخمة لابد أن تكون سرعة الإستجابة لجلب هذه البيانات كبيرة ، فالثواني قد تفرق في حال برمجيات المبيعات التي تتعامل بصورة مباشرة من الزبون مثل أمازون أو غيرها من البرمجيات الضخمة.
بالتالي عندما يقوم المستخدم بجلب البيانات في المرة الأولى، يتوجب علينا تخزين هذه البيانات لفترة محددة من الزمن، في البرمجيات الصغيرة يتم تخزين هذه البيانات في الذاكرة الخاصة بالسيرفر.
لكن ماذا في حال كانت هذه البيانات متداولة بين عدة سيرفرات (خوادم) Web Farm بالتالي سنحتاج آلية لتخزين هذه القطع الصغير من البيانات في مكان آخر.
توجد قاعدة بيانات مصغرة تُسمى Redis وهي مفتوحة المصدر، وهي موجهة لأنظمة التشغيل من النوع Unix-Like تقوم بتخزين هذه القطع من البيانات على الـ Disk بطريقة معينة.
ولكي نقوم بالعمل مع Redis على نظام التشغيل Windows يجب علينا تنزيل هذا الملف الذي توجد به ملفات exe من خلال الرابط التالي
https://github.com/microsoftarchive/redis/releases/tag/win-3.0.504
وكما هو مبين في الصورة التالية:
في هذه المقالة سنري كيفية التعامل مع Redis من خلال ASP.NET Core5.0
أولا بعد إنشاء مشروع ASP.NET Core Web Application قم بفتح الـ Nuget وقم بتنزيل المكتبة التالية Microsoft.Extensions.Caching.StackExchangeRedis
للتعامل مع الـ Cache في الـ ASP.NET Core5.0 توجد واجهة interface تسمى IDistributedCache وبها مجموعة من الأساليب Methods
في هذه المقالة سنحتاج لإسلوبين من هذه الواجهة
(SetStringAsync(key,value,options (GetStringAsync(key
هذان الإسلوبان يقومان بالتعامل مع البيانات على صيغة JSON وتوجد منها أساليب أخرى تتعامل مع البيانات بصيغة Bytes
حسنا سأقوم بإنشاء ملف بإسم Helpers وسأقوم بإنشاء واجهة Interface بإسم IDistributedCacheAdapter وفي نفس هذا المجلد ساقوم بإنشاء فئة Class يرث من الواجهة التي قمنا بإنشاءها بإسم DistributedCacheAdapter ستكون الشفرة بهذه الطريقة:
public interface IDistributedCacheAdapter { Task Store < T > (string key, T data, TimeSpan ? absoluteExpirationRelativeToNow = null, TimeSpan ? slidingExpiration = null); Task < T > Retrieve < T > (string key); }
public class DistributedCacheAdapter: IDistributedCacheAdapter { IDistributedCache _cach; public DistributedCacheAdapter(IDistributedCache cache) { _cach = cache; } public async Task Store < T > (string key, T data, TimeSpan ? absoluteExpirationRelativeToNow = null, TimeSpan ? slidingExpiration = null) { var distributedCacheEntryOptions = new DistributedCacheEntryOptions(); distributedCacheEntryOptions.AbsoluteExpirationRelativeToNow = absoluteExpirationRelativeToNow ?? TimeSpan.FromSeconds(60); distributedCacheEntryOptions.SlidingExpiration = slidingExpiration; var dataToSerialize = System.Text.Json.JsonSerializer.Serialize(data); await _cach.SetStringAsync(key, dataToSerialize); } public async Task < T > Retrieve < T > (string key) { var result = await _cach.GetStringAsync(key); if (result is null) { return default (T); } return System.Text.Json.JsonSerializer.Deserialize < T > (result); } } }
يوجد لدي في هذه الفئة اسلوبان الأول يقوم بتخزين البيانات، والثاني يقوم بإسترجاعها، في اسلوب التخزين Store يوجد متغيران أخيران من النوع TimeSpan
الاول: absoluteExpirationRelativeToNow يقوم بتخزين البيانات على الـ Cache لمدة دقيقة
الثاني: slidingExpiration يقوم بحذف البيانات في حال لم يكون هنالك أي إستدعاء لتلك البيانات في الوقت الذي تقوم أنت المبرمج بتحديده، فرضا في حال قمنا بتحديد دقيقية واحدة ولم يكن هناك أي حركة على شاشة المستخدم In-Active لمدة دقيقة سيقوم الـ Redis بحذف البيانات من على الـ Cache storage
توجد فئة بإسم DistributedCacheEntryOptions وهي التي بها ثلاثة خصائص يتم من خلالها تحديد هذه المدد الزمنية.
لابد من تهيئة Redis من خلال ملف الـ startup.cs وسيكون كالتالي:
services.AddStackExchangeRedisCache(redisOptions => { redisOptions.Configuration = Configuration.GetConnectionString("RedisConn"); redisOptions.InstanceName = "MyApp_"; });
وهنا قم بعمل DI للواجهة والفئة داخل منلف الـ Startup.cs
services.AddScoped < IDistributedCacheAdapter, DistributedCacheAdapter > ();
الخاصية Configuration وهي تُعنى بالربط مع الـ Redis-Server والخاصية InstanceName وهي اسم فريد نقوم بإعطاءه للبيانات التي يتم تخزينها للتطبيق الذي نعمل عليه، لأنه قد يكون لديك أكثر من تطبيق يقوم بإستخدام نفس الـ Redis-Server بالتالي ستقوم بالتفريق بينهم بهذا الإسم.
أيضا بالنسبة للربط بين Redis وقاعدة البيانات التي تعمل عليها سيكون كالتالي داخل ملف الـ appSettings
"ConnectionStrings": { "DBConnectionString": "RedisConn": "localhost:6379" }
في الـ Controller سيكون الكود كالتالي:
[Route("api/[controller]")] [ApiController] public class TestController: ControllerBase { private readonly DataContext _context; private readonly IDistributedCacheAdapter _distributedCacheAdapter; public TestController(DataContext dataContext, IDistributedCacheAdapter distributedCacheAdapter) { _context = dataContext; _distributedCacheAdapter = distributedCacheAdapter; } [HttpGet] public async Task < IActionResult > Get() { var post = await _distributedCacheAdapter.Retrieve < IEnumerable < Post >> ("MyBlogPost"); if (post == null) { post = await _context.Posts.ToListAsync(); await _distributedCacheAdapter.Store("MyBlogPost", post); return new ObjectResult(post); } else { return new ObjectResult(post); } } }
في هذا الكود، قمت بالتأكد من وجود البيانات في الـ Cache فإذا كانت موجودة سيقوم الـ Redis-server بجلبها، وإن لم تكن موجودة سيقوم النظام بجلبها من قاعدة البيانات وفي نفس الوقت قمت بتخزينها على الـ Redis-server وحتى يتسنى لي في الرة القادمة في حالقام المستخدم بإستدعائها مرة أخرى حينها سيتسنى لي جلبها من الـ Redis-server.
حسنا قبل عمل تشغيل للنظام قم بفتح الملف الذي قمت بتنزيله في بداية المقالة وقم بتشغيل ملف redis-server.exe سيكون كالتالي كما موضح بالصورة، وهذه سيتيح لنا إمكانية التعامل مع الـ Redis كسيرفر (خادم) نسبة لأننا نعمل على بيئة Windows
يقوم الخادم بالعمل على الـ IP 127.0.0.1 وعلى المنفذ 6379 وبإمكانك تغييرهم إذا أردت. (قم بالذهاب لآخر المقالة لمعرفة من أين يمكن تغيير هذه الإعدادت)
بعد فتح الـ redis-server.exe قم بفتح الـ redis-cli.exe وقم بتنفيذ الأمر ping وفي حال كان الإتصال يعمل بصورة طبيعية سيقوم بالرد برسالة PONG.
وكما ترى في الصورة لقد قمت بتنفيذ الأمر scan 0 وذلك حتى أتأكد من أنه لا توجد أي بيانات مخزنة مسبقا، وبعد تنفيذ التطبيق سنقوم بتنفيذ هذا الأمر مجددا لنرى أنه هنالك بيانات تم تخزينها بعد أول Request فبالتالي عندها نقوم بعمل Request ثاني سيتم جلب البيانات من الـ Redis server.
أقوم بإستخدام قاعدة بيانات من النوع PostgreSQL ولدي جدول واحد في قاعدة بيانات بإسم Test_DB والجدول بإسم Posts وبه أربعة حقول وهذا الجدول به 1000 سطر من البيانات، و كما موضح الـ Schema الخاصة بهذا الجدول في الصورة التالية:
الآن إذا قمت بتنفيذ النظام وفتح الـ Post man وعمل إستدعاء للـ Action Methods سيقوم النظام بمخاطبة قاعدة البيانات في المرة الاولى، وسيقوم بتخزين البيانات على الـ Cache وفي المرة الثانية سيقوم بإستدعائها من الـ Cache بدلا من مخاطبة قاعدة البيانات مرة أخرى، لاحظ للمدد الزمنية في الـ Request الأول، والـ Request الثاني والـ Request الثالث
الـ Request الاول مدته 3 ثواني والثاني 159 ملي ثانية والثالث 84 ملي ثانية
(أعتقد أن الفرق بين الـ Requests كافي لأن يعمل النظام بصورة بها أداء عالي جدا من الكفاءة)
أخيراً: أقوم بإستخدام Redis من خلال السيرفر الخاص بي (الخادم) والذي يعمل على نظام التشغيل FreeDSB ومن خلاله أقوم بتثبيت الـ IP الذي أود التعامل معه من على الـ Production وأقوم بعمل الإعدادات داخل ملف redis.conf وكما موضح بالصور التالية:
تحياتي.
[…] post التعامل مع الـ Caching في الـ ASP.NET Core من خلال Redis appeared first on […]