حلول تخزين مؤقت موزع عالية الأداء وقابلة للتوسع باستخدام Redis في معماريات الخدمات المصغرة
تسمح معماريات الخدمات المصغرة الحديثة المستندة إلى السحابة بتوسيع وتطوير أجزاء مختلفة من التطبيق بشكل مستقل. ومع ذلك، يمكن أن يؤدي هذا الهيكل الموزع إلى اختناقات في الأداء بسبب زمن استجابة الشبكة وحمل قاعدة البيانات. إحدى الطرق الأكثر فعالية للتغلب على هذه المشكلات هي استخدام التخزين المؤقت الموزع (distributed caching).
لماذا التخزين المؤقت الموزع؟
تقليديًا، غالبًا ما تستخدم التطبيقات ذاكرات التخزين المؤقت المحلية (في الذاكرة). ومع ذلك، يمكن أن تستضيف الخدمات المصغرة مثيلات خدمة متعددة تصل إلى نفس البيانات. تؤدي ذاكرات التخزين المؤقت المحلية إلى عدم الاتساق في هذا السيناريو، ويجب على كل مثيل خدمة إدارة ذاكرة التخزين المؤقت الخاصة به. من ناحية أخرى، يحل التخزين المؤقت الموزع هذه المشكلات من خلال توفير طبقة تخزين بيانات مركزية مشتركة بين جميع مثيلات الخدمة. يقلل هذا النهج من:
- العبء على قاعدة البيانات.
- يقلل بشكل كبير من أوقات الوصول إلى البيانات (غالبًا من ميلي ثانية إلى ميكرو ثانية).
- يزيد من قابلية توسع التطبيق، حيث يصبح الأداء معتمدًا على طبقة التخزين المؤقت بدلاً من قاعدة البيانات.
مقدمة إلى Redis
Redis (خادم القاموس عن بعد) هو مخزن هياكل بيانات عالي الأداء ومفتوح المصدر وفي الذاكرة. يستخدم عادةً كذاكرة تخزين مؤقت ووسيط رسائل وقاعدة بيانات. يوفر بنية تخزين مفتاح-قيمة وأنواع بيانات متنوعة مثل السلاسل والتجزئات والقوائم والمجموعات. تلغي خدمات Redis المدارة التي توفرها موفري الخدمات السحابية (AWS ElastiCache، Azure Cache for Redis، Google Cloud Memorystore) عبء الإعداد والإدارة، مما يسمح للمطورين بالتركيز فقط على منطق التخزين المؤقت.
تطبيق عملي: تكامل Redis في الخدمات المصغرة
الآن، دعنا نلقي نظرة على مثال عملي لكيفية استخدام Redis كذاكرة تخزين مؤقت موزعة من خلال خدمة مصغرة بسيطة مبنية على .NET. يتضمن السيناريو الخاص بنا خدمة كتالوج منتجات تقوم بتخزين تفاصيل المنتجات التي يتم الوصول إليها بشكل متكرر مؤقتًا.
الخطوة 1: اتصال وتكوين Redis
أولاً، نحتاج إلى الاتصال بـ Redis في تطبيق الخدمات المصغرة الخاص بنا. سنستخدم StackExchange.Redis، وهي مكتبة شائعة لـ .NET.
using StackExchange.Redis; public class RedisCacheService { private readonly ConnectionMultiplexer _redis; private readonly IDatabase _database; public RedisCacheService(string connectionString) { _redis = ConnectionMultiplexer.Connect(connectionString); _database = _redis.GetDatabase(); } public IDatabase GetDatabase() { return _database; } } عادةً ما يحتوي connectionString على عنوان ومنفذ خادم Redis (على سبيل المثال: "myredis.cache.windows.net:6380,password=...,ssl=True,abortConnect=False").
الخطوة 2: استراتيجيات التخزين المؤقت واسترجاع البيانات (نمط Cache-Aside)
أحد أنماط التخزين المؤقت الأكثر شيوعًا، نمط Cache-Aside، يبحث أولاً عن البيانات في ذاكرة التخزين المؤقت، وإذا لم يتم العثور عليها، يقوم بجلبها من قاعدة البيانات وكتابتها إلى ذاكرة التخزين المؤقت للطلبات اللاحقة. في المثال أدناه، لنفترض أننا نقوم بتخزين واسترجاع كائن Product مؤقتًا.
using System.Text.Json; public class Product { public int Id { get; set; } public string Name { get; set; } public decimal Price { get; set; } } public class ProductService { private readonly IDatabase _cache; private readonly IProductRepository _repository; // للوصول إلى قاعدة البيانات private const string CacheKeyPrefix = "product:"; public ProductService(RedisCacheService redisService, IProductRepository repository) { _cache = redisService.GetDatabase(); _repository = repository; } public async Task<Product> GetProductByIdAsync(int productId) { string cacheKey = $"{CacheKeyPrefix}{productId}"; string cachedProductJson = await _cache.StringGetAsync(cacheKey); if (!string.IsNullOrEmpty(cachedProductJson)) { return JsonSerializer.Deserialize<Product>(cachedProductJson); } // لم يتم العثور عليه في ذاكرة التخزين المؤقت، قم بالاسترداد من قاعدة البيانات Product product = await _repository.GetProductByIdAsync(productId); if (product != null) { // اكتب المنتج الذي تم جلبه من قاعدة البيانات إلى ذاكرة التخزين المؤقت، صالح لمدة 5 دقائق await _cache.StringSetAsync(cacheKey, JsonSerializer.Serialize(product), TimeSpan.FromMinutes(5)); } return product; } public async Task<bool> UpdateProductAsync(Product product) { bool success = await _repository.UpdateProductAsync(product); if (success) { // إلغاء صلاحية ذاكرة التخزين المؤقت عند تحديث المنتج string cacheKey = $"{CacheKeyPrefix}{product.Id}"; await _cache.KeyDeleteAsync(cacheKey); } return success; } } كائن product.
الخطوة 3: إدارة تناسق ذاكرة التخزين المؤقت
يعد الحفاظ على تحديث البيانات المخزنة مؤقتًا أمرًا بالغ الأهمية. كما ترى في طريقة UpdateProductAsync أعلاه، يمكننا إجراء إلغاء صلاحية يدوي عن طريق حذف مفتاح ذاكرة التخزين المؤقت ذي الصلة (KeyDeleteAsync) عند تحديث البيانات. بالإضافة إلى ذلك:
- TTL (وقت البقاء): يضمن تعيين حد زمني للبيانات المخزنة مؤقتًا إلغاء صلاحيتها تلقائيًا بعد فترة زمنية محددة (
TimeSpan.FromMinutes(5)في المثال أعلاه). - نموذج Pub/Sub: في السيناريوهات الأكثر تعقيدًا، يمكننا استخدام ميزة Pub/Sub (النشر/الاشتراك) في Redis لإخطار الخدمات المصغرة الأخرى عندما تقوم خدمة مصغرة بتحديث البيانات. يتم إرسال رسالة التحديث إلى قناة، ويمكن لجميع الخدمات المهتمة إلغاء صلاحية ذاكرات التخزين المؤقت الخاصة بها.
أفضل الممارسات
- تصميم المفتاح: صمم مفاتيح ذاكرة التخزين المؤقت الخاصة بك لتكون متسقة وقابلة للقراءة ومقاومة للتصادم (على سبيل المثال:
"product:{id}"،"user:{id}:profile"). - تسلسل البيانات: قبل كتابة البيانات إلى Redis، قم بتسلسلها باستخدام تنسيقات فعالة مثل JSON أو MessagePack. يمكن أيضًا تفضيل البيانات المضغوطة لتحسين الأداء.
- حجم ذاكرة التخزين المؤقت وسياسات الإخلاء: احرص على عدم تجاوز ذاكرة الخادم الذي يستضيف Redis. قم بتحسين إدارة الذاكرة لديك باستخدام إعدادات مثل
maxmemoryوسياسات الإخلاء مثل LRU (الأقل استخدامًا مؤخرًا) أو LFU (الأقل استخدامًا تكرارًا). - إدارة شروط السباق: فكر في استخدام آليات قفل موزع مثل أمر
SETNX(تعيين إذا لم يكن موجودًا) في Redis أو خوارزمية Redlock لمنع شروط السباق التي يمكن أن تحدث أثناء الوصول المتزامن إلى نفس المورد في الأنظمة الموزعة. - معالجة الأخطاء وقاطع الدائرة: عالج الأخطاء التي تحدث أثناء الوصول إلى ذاكرة التخزين المؤقت. قم بتطبيق نمط قاطع الدائرة لمنع تعطل تطبيقك بالكامل عندما يتعذر الوصول إلى Redis، وتأكد من سقوطه مباشرة إلى قاعدة البيانات.
- المراقبة والتنبيهات: راقب أداء خادم Redis الخاص بك بانتظام (وحدة المعالجة المركزية، استخدام الذاكرة، عدد الاتصالات، نسبة النجاح/الفشل) وقم بتكوين التنبيهات للحالات غير الطبيعية.
الخلاصة
يعد التخزين المؤقت الموزع استراتيجية لا غنى عنها لزيادة الأداء وقابلية التوسع في معماريات الخدمات المصغرة المستندة إلى السحابة. يعد Redis، بفضل ميزاته الغنية وأدائه العالي، أداة ممتازة لتلبية هذه الحاجة. عند تطبيقه بالاستراتيجيات الصحيحة وأفضل الممارسات، سيمكن Redis خدماتك المصغرة من العمل بشكل أسرع وأكثر كفاءة ومرونة.
التعليقات (0)
لا توجد تعليقات بعد. كن أول من يعلق!