التخزين المؤقت في JavaScript: Redis وMemcached والحلول المدمجة (مستوى متقدم)

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

التخزين المؤقت في JavaScript: Redis وMemcached والحلول المدمجة (مستوى متقدم)

\n\n

في تطوير الويب الحديث، غالبًا ما يعتمد أداء التطبيق على سرعة الوصول إلى البيانات. كل طلب إضافي لقاعدة البيانات أو API خارجي يزيد من وقت الاستجابة والتحميل على الخادم. التخزين المؤقت ليس مجرد "حفظ النتيجة"، بل هو علم كامل يتضمن اختيار الاستراتيجية الصحيحة والأداة وآلية الإبطال. في هذه المقالة، سنستعرض التقنيات المتقدمة للتخزين المؤقت في Node.js: من الحلول المدمجة إلى الأنظمة الصناعية Redis وMemcached.

\n\n

1. التخزين المؤقت المدمج في Node.js: البساطة والقيود

\n\n

قبل ربط الخدمات الخارجية، يجدر تقييم إمكانيات Node.js نفسه. يتم تنفيذ التخزين المؤقت المدمج باستخدام كائنات Map أو WeakMap، بالإضافة إلى المتغيرات العامة البسيطة. هذا مثالي للبيانات التي نادرًا ما تتغير وتعيش ضمن عملية واحدة.

\n\n
// أبسط ذاكرة تخزين مؤقت في الذاكرة مع TTL (وقت الحياة)\nclass MemoryCache {\n  constructor(ttl = 60000) {\n    this.cache = new Map();\n    this.ttl = ttl;\n  }\n\n  set(key, value) {\n    this.cache.set(key, {\n      value,\n      expiry: Date.now() + this.ttl\n    });\n  }\n\n  get(key) {\n    const item = this.cache.get(key);\n    if (!item) return null;\n    if (Date.now() > item.expiry) {\n      this.cache.delete(key);\n      return null;\n    }\n    return item.value;\n  }\n\n  delete(key) {\n    this.cache.delete(key);\n  }\n\n  clear() {\n    this.cache.clear();\n  }\n}\n\n// الاستخدام\nconst cache = new MemoryCache(30000); // TTL 30 ثانية\ncache.set('user:42', { name: 'Alice', role: 'admin' });\nconsole.log(cache.get('user:42')); // { name: 'Alice', role: 'admin' }\n
\n\n

الإيجابيات: زمن انتقال صفري للشبكة، سهولة التنفيذ، لا يتطلب تبعيات خارجية.
\nالسلبيات: فقدان البيانات عند إعادة تشغيل العملية، لا يتوسع عبر خوادم متعددة، محدود بذاكرة الوصول العشوائي لعقدة واحدة.

\n\n

بالنسبة للخدمات المصغرة التي تعمل في عملية واحدة، أو لتخزين نتائج الحسابات الثقيلة (مثل عرض القوالب)، فإن الحل المدمج هو اختيار ممتاز. ومع ذلك، فهو غير كافٍ للأنظمة الموزعة.

\n\n

2. Redis: ملك التخزين المؤقت في Node.js

\n\n

Redis هو مخزن بيانات في الذاكرة يُستخدم غالبًا كذاكرة تخزين مؤقت عالية الأداء. مزاياه الرئيسية: دعم هياكل البيانات المعقدة (سلاسل، قوائم، مجموعات، تجزئات)، TTL مدمج، pub/sub، والثبات على القرص.

\n\n

ربط Redis في Node.js

\n\n

للعمل مع Redis في Node.js، يُستخدم الحزمة ioredis (موصى بها) أو redis. لنلقِ نظرة على مثال باستخدام ioredis:

\n\n
const Redis = require('ioredis');\n\nconst redis = new Redis({\n  host: 'localhost',\n  port: 6379,\n  retryStrategy: (times) => Math.min(times * 50, 2000) // استراتيجية إعادة الاتصال\n});\n\n// العمليات الأساسية\nawait redis.set('mykey', 'Hello, Redis!', 'EX', 60); // TTL 60 ثانية\nconst value = await redis.get('mykey');\nconsole.log(value); // "Hello, Redis!"\n\n// استخدام التجزئة لتخزين الكائنات المعقدة\nawait redis.hmset('user:100', {\n  name: 'Bob',\n  email: 'bob@example.com',\n  age: 30\n});\nconst user = await redis.hgetall('user:100');\nconsole.log(user); // { name: 'Bob', email: 'bob@example.com', age: '30' }\n
\n\n

استراتيجيات متقدمة مع Redis

\n\n

Cache-Aside (التحميل البطيء): يتحقق التطبيق أولاً من التخزين المؤقت، وعند عدم وجود البيانات فقط يتصل بقاعدة البيانات ويملأ التخزين المؤقت.

\n\n
async function getUser(userId) {\n  const cacheKey = `user:${userId}`;\n  let user = await redis.get(cacheKey);\n  if (user) {\n    return JSON.parse(user);\n  }\n  // عدم وجود البيانات في التخزين المؤقت - تحميل من قاعدة البيانات\n  user = await db.findUserById(userId);\n  if (user) {\n    await redis.set(cacheKey, JSON.stringify(user), 'EX', 3600); // تخزين مؤقت لمدة ساعة\n  }\n  ret                

المدونات

توصيات الكتب