اتصال Node.js به Redis
Redis یک پایگاه داده در حافظه (in-memory) با کارایی بسیار بالا است که برای کش، صفها، شمارشگرها و pub/sub بسیار مناسب است. در این مقاله به زبان فارسی و بهصورت کاربردی به نحوه اتصال و استفاده از Redis در محیط Node.js میپردازیم، مزایا، مثالهای عملی، پیکربندی اتصال، نکات امنیتی و بهینهسازیهای متداول را پوشش میدهیم.
پیشنیازها
- Node.js (نسخه 14+ توصیه میشود)
- نصب Redis روی سرور محلی یا سرویس managed مانند Redis Labs / AWS ElastiCache
- کتابخانه کلاینت: node-redis (official) یا ioredis
نصب کتابخانه
npm install redis
# یا برای ioredis
npm install ioredisاین دستورها کتابخانههای محبوب را نصب میکنند. node-redis از نسخهٔ 4 به بعد API مدرن و Promise-based ارائه میدهد و ioredis قابلیتهای پیشرفتهای مثل کلستر و Sentinel را دارد.
نمونه اتصال ساده با node-redis (نسخه مدرن)
const { createClient } = require('redis');
async function main() {
const client = createClient({
url: 'redis://:password@localhost:6379'
});
client.on('error', (err) => console.error('Redis Client Error', err));
await client.connect();
await client.set('visits', 0);
const visits = await client.incr('visits');
console.log('Visits:', visits);
await client.quit();
}
main().catch(console.error);در این کد، یک کلاینت Redis ساخته و به سرور وصل میشویم. سپس یک کلید ‘visits’ مقداردهی اولیه و با incr مقدار آن افزایش مییابد. در پایان اتصال بسته میشود. از رویکرد async/await و event ‘error’ برای دریافت خطاها استفاده شده است.
اتصال با ioredis و پشتیبانی از کلستر/Sentinel
const Redis = require('ioredis');
// اتصال به Sentinel
const client = new Redis({
sentinels: [{ host: '127.0.0.1', port: 26379 }],
name: 'mymaster',
password: 'password'
});
// یا اتصال به کلستر
// const cluster = new Redis.Cluster([
// { host: '127.0.0.1', port: 7000 },
// { host: '127.0.0.1', port: 7001 },
// ]);ioredis برای محیطهای production با نیاز به High Availability مناسب است. در مثال بالا اتصال به Sentinel نشان داده شده که به صورت خودکار مستر را پیدا و مدیریت میکند. نمونهٔ کلستر نیز نشان دهنده اتصال به چند نود است.
مثال: استفاده از Redis بهعنوان cache در Express
const express = require('express');
const { createClient } = require('redis');
const client = createClient();
client.connect();
const app = express();
async function cacheMiddleware(req, res, next) {
const key = `cache:${req.originalUrl}`;
const cached = await client.get(key);
if (cached) {
return res.send(JSON.parse(cached));
}
res.sendResponse = res.send;
res.send = (body) => {
client.setEx(key, 60, JSON.stringify(body)); // cache for 60s
res.sendResponse(body);
};
next();
}
app.get('/data', cacheMiddleware, async (req, res) => {
const data = { time: Date.now(), value: Math.random() };
res.send(data);
});
app.listen(3000);این میدلور یک خروجی را برای 60 ثانیه کش میکند. ابتدا از Redis برای خواندن کش استفاده میشود و در صورت نبود، پاسخ اصلی تولید و در Redis با TTL ذخیره میگردد.
پایپلاین، تراکنش و اجرای چند فرمان
const { createClient } = require('redis');
async function pipelineExample() {
const client = createClient();
await client.connect();
const pipeline = client.multi(); // یا pipeline() در بعضی کلاینتها
pipeline.set('a', 1);
pipeline.incr('a');
pipeline.get('a');
const results = await pipeline.exec();
console.log(results);
await client.quit();
}پایپلاین یا multi باعث میشود چند فرمان پشتسرهم ارسال شده و در صورت استفاده از multi/exec اتمیک اجرا شوند. این شیوه برای کاهش ترافیک شبکه و افزایش سرعت مناسب است.
Pub/Sub ساده
// Publisher
const { createClient } = require('redis');
const pub = createClient();
await pub.connect();
await pub.publish('channel1', 'hello');
// Subscriber
const sub = createClient();
await sub.connect();
sub.subscribe('channel1', (message) => {
console.log('Received:', message);
});Pub/Sub برای اطلاعرسانیهای real-time مفید است، اما توجه کنید که پیامها در Redis ذخیره نمیشوند و اگر مشترک قبل از انتشار نباشد، پیام را از دست میدهد. برای صفهای پایدار بهتر است از لیستها یا Stream استفاده کنید.
مقایسه کوتاه node-redis و ioredis
| ویژگی | node-redis | ioredis |
|---|---|---|
| سازنده رسمی | بله | خیر (پشتیبانی قوی از کلستر) |
| API مدرن | Promise-based | Promise و event-based |
| پشتیبانی از Cluster/Sentinel | محدودتر | قوی و کامل |
نکات عملی و Best Practices
- مدیریت اتصال: از reconnect و backoff strategy استفاده کنید تا در مواقع قطع ارتباط، کلاینت به صورت خودکار تلاش به اتصال مجدد کند.
- TTL مناسب: برای کش از TTL استفاده کنید تا حافظه کنترل شود و استراتژی invalidation مشخص باشد.
- عدم ذخیره اشیاء بزرگ: سریالایزینگ اشیاء بزرگ میتواند حافظه را پر کند؛ بهجای آن دادهها را به اجزاء کوچکتر تقسیم کنید.
- استفاده از هَشها (Hashes): برای ذخیرهٔ آبجکتها که نیاز به دسترسی به فیلدهای جداگانه دارند بهتر است از HSET/HGET استفاده شود.
- نظارت بر eviction و memory: در محیط تولید از متریکها و ALERT برای اندازهٔ حافظه و policyهای eviction استفاده کنید.
- امنیت: از AUTH، فایروال و TLS برای محافظت ترافیک استفاده کنید.
نمونهٔ بهبود: reconnect با backoff در node-redis
const { createClient } = require('redis');
function createRedisClient() {
const client = createClient({
socket: {
host: 'localhost',
port: 6379,
reconnectStrategy: (retries) => {
// exponential backoff capped
if (retries >= 10) return new Error('Too many retries');
return Math.min(1000 * 2 ** retries, 30000);
}
}
});
client.on('error', (err) => console.error('Redis error', err));
return client;
}در این کد از reconnectStrategy برای پیادهسازی backoff نمایی استفاده شده است تا در صورت قطع اتصال، تلاشهای مجدد با تاخیر افزایشی انجام شود و در نهایت از تلاش بیش از حد جلوگیری گردد.
موارد استفاده عملی
- کش کردن نتایج API برای کاهش بار دیتابیس
- صف پیام با استفاده از لیستها (LPUSH/BRPOP) یا Streams
- شمارندهها و نرخدهی (rate limiting)
- سیستمهای real-time با pub/sub
- ذخیرهٔ نمایشهای موقت، session و feature flags
جمعبندی و توصیهٔ نهایی
اتصال Node.js به Redis ساده و قدرتمند است، اما برای استفادهٔ بهینه باید به مدیریت اتصال، سیاستهای TTL، انتخاب کلاینت مناسب (node-redis یا ioredis)، و نظارت بر حافظه توجه کنید. در محیطهای توزیعشده از Sentinel یا Cluster و در محیطهای حساس به تأخیر از pipelining و multi/exec بهره ببرید.
در صورت نیاز میتوانم نمونهٔ کاملتری از پیادهسازی کش لایهٔ میانی، مدیریت خطا و مانیتورینگ Redis در پروژهٔ شما تهیه کنم.
آیا این مطلب برای شما مفید بود ؟




