Redis مع Node.js
Redis مع Node.js
في هذا الدرس، سنتعلم كيفية دمج Redis مع تطبيقات Node.js باستخدام مكتبة ioredis، وهي واحدة من أكثر عملاء Redis شعبية وثراءً بالميزات لـ Node.js.
تثبيت ioredis
أولاً، قم بتثبيت حزمة ioredis في مشروع Node.js الخاص بك:
يمكنك أيضاً التثبيت باستخدام yarn:
الاتصال الأساسي
إليك كيفية إنشاء اتصال أساسي بـ Redis:
// الاتصال بـ localhost:6379 الافتراضي
const redis = new Redis();
// أو تحديد خيارات الاتصال
const redisCustom = new Redis({
host: '127.0.0.1',
port: 6379,
password: 'your_password',
db: 0
});
الاتصال باستخدام متغيرات البيئة
أفضل ممارسة هي استخدام متغيرات البيئة للتكوين:
const Redis = require('ioredis');
const redis = new Redis({
host: process.env.REDIS_HOST || 'localhost',
port: process.env.REDIS_PORT || 6379,
password: process.env.REDIS_PASSWORD,
db: process.env.REDIS_DB || 0,
retryStrategy: (times) => {
const delay = Math.min(times * 50, 2000);
return delay;
}
});
.env مع بيانات اعتماد Redis الخاصة بك: REDIS_HOST=localhost, REDIS_PORT=6379, REDIS_PASSWORD=your_passwordالعمليات الأساسية
تنفيذ عمليات Redis الأساسية مع ioredis:
await redis.set('user:1000', 'John Doe');
// أمر GET
const username = await redis.get('user:1000');
console.log(username); // 'John Doe'
// SET مع انتهاء الصلاحية (EX بالثواني)
await redis.set('session:abc123', 'user_data', 'EX', 3600);
// SETEX (اختصار لـ SET مع انتهاء الصلاحية)
await redis.setex('token:xyz789', 1800, 'auth_token_value');
// أمر DEL
await redis.del('user:1000');
// أمر EXISTS
const exists = await redis.exists('user:1000');
console.log(exists); // 0 (false) أو 1 (true)
العمل مع بيانات JSON
تخزين واسترجاع كائنات JavaScript كسلاسل JSON:
id: 1000,
name: 'John Doe',
email: 'john@example.com',
role: 'admin'
};
// تخزين الكائن كسلسلة JSON
await redis.set('user:1000', JSON.stringify(user));
// الاسترجاع والتحليل
const userData = await redis.get('user:1000');
const parsedUser = JSON.parse(userData);
console.log(parsedUser.name); // 'John Doe'
عمليات Hash
تجزئات Redis مثالية لتخزين الكائنات بدون تسلسل JSON:
await redis.hset('user:1000', 'name', 'John Doe');
await redis.hset('user:1000', 'email', 'john@example.com');
// HMSET - تعيين حقول متعددة دفعة واحدة
await redis.hmset('user:1001', {
name: 'Jane Smith',
email: 'jane@example.com',
age: 28
});
// HGET - الحصول على حقل واحد
const name = await redis.hget('user:1000', 'name');
// HGETALL - الحصول على جميع الحقول
const user = await redis.hgetall('user:1000');
console.log(user); // { name: 'John Doe', email: 'john@example.com' }
// HDEL - حذف حقل
await redis.hdel('user:1000', 'email');
أحداث الاتصال
مراقبة حالة اتصال Redis باستخدام مستمعي الأحداث:
const redis = new Redis();
redis.on('connect', () => {
console.log('✓ متصل بـ Redis');
});
redis.on('ready', () => {
console.log('✓ Redis جاهز لقبول الأوامر');
});
redis.on('error', (err) => {
console.error('✗ خطأ Redis:', err);
});
redis.on('close', () => {
console.log('تم إغلاق الاتصال');
});
redis.on('reconnecting', () => {
console.log('إعادة الاتصال بـ Redis...');
});
معالجة الأخطاء
قم دائماً بتنفيذ معالجة صحيحة للأخطاء عند العمل مع Redis:
try {
const userData = await redis.get(`user:${userId}`);
if (!userData) {
return null;
}
return JSON.parse(userData);
} catch (error) {
console.error('خطأ Redis GET:', error);
throw new Error('فشل استرجاع بيانات المستخدم');
}
}
async function setUserData(userId, data) {
try {
await redis.setex(
`user:${userId}`,
3600,
JSON.stringify(data)
);
return true;
} catch (error) {
console.error('خطأ Redis SET:', error);
return false;
}
}
الإيقاف الرشيق
أغلق دائماً اتصالات Redis عند إيقاف تطبيقك:
process.on('SIGTERM', async () => {
console.log('تم استلام SIGTERM، إغلاق اتصال Redis...');
await redis.quit();
process.exit(0);
});
process.on('SIGINT', async () => {
console.log('تم استلام SIGINT، إغلاق اتصال Redis...');
await redis.quit();
process.exit(0);
});
redis.quit() للإيقاف الرشيق (ينتظر الأوامر المعلقة) أو redis.disconnect() للانفصال الفوري.تجميع الاتصالات
للتطبيقات ذات التزامن العالي، تدير ioredis تلقائياً تجميع الاتصالات:
const redis = new Redis({
host: 'localhost',
port: 6379,
maxRetriesPerRequest: 3,
enableReadyCheck: true,
enableOfflineQueue: true,
connectTimeout: 10000,
lazyConnect: false
});