रेडिस एक इन-मेमोरी डेटा स्टोर है जो महंगे डेटाबेस प्रश्नों और एपीआई प्रतिक्रियाओं को कैश करके अनुप्रयोगों को नाटकीय रूप से गति देता है। एक अच्छी तरह से रखा गया कैश 200ms डेटाबेस क्वेरी को 2ms कैश हिट में बदल सकता है। यह मार्गदर्शिका Redis कैशिंग को Node.js ऐप में सही तरीके से जोड़ती है।
📋 Table of Contents
रेडिस के साथ कैश क्यों?
- गति: इन-मेमोरी रीड्स डेटाबेस क्वेरीज़ की तुलना में 10-100 गुना तेज़ हैं
- डेटाबेस लोड कम करें: अपने डेटाबेस को बचाते हुए, कैश से बार-बार किए गए अनुरोधों को पूरा करें
- स्केल: अपने प्राथमिक डेटास्टोर पर दबाव डाले बिना ट्रैफ़िक में बढ़ोतरी को संभालें
- बहुमुखी: सत्र, दर सीमित करना, कतारें और पब/उप
को भी संभालता है सेटअप
npm install ioredis
# Run Redis locally with Docker
docker run -d --name redis -p 6379:6379 redis:7-alpine
// redis.js — connection singleton
import Redis from 'ioredis';
export const redis = new Redis({
host: process.env.REDIS_HOST || 'localhost',
port: parseInt(process.env.REDIS_PORT || '6379'),
maxRetriesPerRequest: 3,
retryStrategy: (times) => Math.min(times * 50, 2000),
});
redis.on('error', (err) => console.error('Redis error:', err));
redis.on('connect', () => console.log('Redis connected'));
कैश-असाइड पैटर्न (सबसे आम)
पहले कैश जांचें; चूक जाने पर, डेटाबेस से प्राप्त करें और कैश को पॉप्युलेट करें:
import { redis } from './redis';
async function getUser(userId) {
const cacheKey = `user:${userId}`;
// 1. Try cache first
const cached = await redis.get(cacheKey);
if (cached) {
return JSON.parse(cached); // cache hit — fast path
}
// 2. Cache miss — fetch from database
const user = await db.users.findById(userId);
if (!user) return null;
// 3. Populate cache with a TTL (expire after 1 hour)
await redis.set(cacheKey, JSON.stringify(user), 'EX', 3600);
return user;
}
पुन: प्रयोज्य कैश रैपर
async function cached(key, ttlSeconds, fetchFn) {
const hit = await redis.get(key);
if (hit) return JSON.parse(hit);
const data = await fetchFn();
if (data !== null && data !== undefined) {
await redis.set(key, JSON.stringify(data), 'EX', ttlSeconds);
}
return data;
}
// Usage — clean and reusable
const products = await cached('products:featured', 600, () =>
db.products.findFeatured()
);
const user = await cached(`user:${id}`, 3600, () =>
db.users.findById(id)
);
कैश अमान्यकरण (कठिन भाग)
// When data changes, invalidate the cache to avoid stale reads
async function updateUser(userId, updates) {
const user = await db.users.update(userId, updates);
// Invalidate the cached version
await redis.del(`user:${userId}`);
// Invalidate related caches too
await redis.del('users:list');
return user;
}
// Invalidate by pattern (use SCAN, not KEYS, in production)
async function invalidatePattern(pattern) {
const stream = redis.scanStream({ match: pattern, count: 100 });
stream.on('data', (keys) => {
if (keys.length) redis.del(...keys);
});
}
// invalidatePattern('user:*'); // clear all user caches
रूट कैशिंग के लिए एक्सप्रेस मिडलवेयर
function cacheRoute(ttlSeconds) {
return async (req, res, next) => {
const key = `route:${req.originalUrl}`;
const cached = await redis.get(key);
if (cached) {
res.setHeader('X-Cache', 'HIT');
return res.json(JSON.parse(cached));
}
// Override res.json to cache the response
const originalJson = res.json.bind(res);
res.json = (body) => {
redis.set(key, JSON.stringify(body), 'EX', ttlSeconds);
res.setHeader('X-Cache', 'MISS');
return originalJson(body);
};
next();
};
}
// Cache this route for 5 minutes
app.get('/api/products', cacheRoute(300), getProducts);
रेडिस के साथ दर सीमित करना
async function rateLimit(req, res, next) {
const key = `ratelimit:${req.ip}`;
const limit = 100; // requests
const window = 60; // seconds
const current = await redis.incr(key);
if (current === 1) {
await redis.expire(key, window); // set TTL on first request
}
if (current > limit) {
return res.status(429).json({ error: 'Too many requests' });
}
res.setHeader('X-RateLimit-Remaining', Math.max(0, limit - current));
next();
}
कैशिंग सर्वोत्तम अभ्यास
- हमेशा एक TTL सेट करें: पुराने डेटा को हमेशा के लिए जीवित रहने से रोकता है और मेमोरी को नियंत्रित करता है
- कैश क्या महँगा है और बार-बार पढ़ें: हर चीज़ को कैश न करें – हॉट पाथ को कैश करें
- कैश विफलताओं को शालीनता से संभालें: यदि रेडिस डाउन है, तो डेटाबेस तक पहुंचें, क्रैश न करें
- सुसंगत कुंजी नामकरण का प्रयोग करें:
entity:id:fieldकन्वेंशन अमान्यकरण को पूर्वानुमेय बनाते हैं - उत्पादन में KEYS कमांड से बचें: यह Redis को अवरुद्ध करता है – इसके बजाय SCAN का उपयोग करें
- कैश भगदड़ पर नजर रखें: जब एक लोकप्रिय कुंजी समाप्त हो जाती है, तो कई अनुरोध एक साथ डेटाबेस पर आते हैं – ताले या कंपित टीटीएल का उपयोग करें
अक्सर पूछे जाने वाले प्रश्न
प्रश्न: मुझे क्या कैश नहीं करना चाहिए?
उत्तर: अत्यधिक अस्थिर डेटा जो हर अनुरोध को बदल देता है, उचित सुरक्षा के बिना संवेदनशील डेटा और गणना करने के लिए सस्ता डेटा। महंगे, बार-बार पढ़े जाने वाले, अपेक्षाकृत-स्थिर डेटा को कैश करें।
प्रश्न: मैं टीटीएल कैसे चुनूं?
ए: ताजगी बनाम प्रदर्शन को संतुलित करें। उपयोगकर्ता प्रोफ़ाइल: 1 घंटा. उत्पाद सूची: 5-10 मिनट। वास्तविक समय डेटा: सेकंड या कैश न करें। टीटीएल का मिलान इस बात से करें कि डेटा वास्तव में कितनी बार बदलता है।
प्रश्न: यदि रेडिस नीचे चला जाए तो क्या होगा?
उ: आपके ऐप को शानदार ढंग से डीग्रेड होना चाहिए – रेडिस त्रुटियों को पकड़ें और डेटाबेस तक पहुंचें। कैश विफलता को कभी भी अपना ऐप बंद न करने दें। कैश कॉल को ट्राई/कैच में लपेटें।
प्रश्न: रेडिस बनाम इन-मेमोरी कैशिंग (जेएस मैप की तरह)?
ए: इन-मेमोरी मैप कैश प्रति-प्रक्रिया है (पुनः आरंभ होने पर खो जाता है, इंस्टेंसेस में साझा नहीं किया जाता है)। रेडिस आपके सभी ऐप इंस्टेंस पर साझा किया जाता है और बना रहता है – क्षैतिज रूप से स्केल किए गए ऐप्स के लिए आवश्यक।
प्रश्न: मैं कैश भगदड़ को कैसे रोकूँ?
उत्तर: लॉक (SET NX) का उपयोग करें ताकि केवल एक अनुरोध कैश को ताज़ा कर सके जबकि अन्य प्रतीक्षा करें या पुराना डेटा परोसें, या TTL में यादृच्छिक जिटर जोड़ें ताकि सभी लोकप्रिय कुंजियाँ एक साथ समाप्त न हों।
निष्कर्ष
Redis कैशिंग आपके Node.js ऐप के प्रदर्शन को बदल सकता है – धीमी डेटाबेस क्वेरी को तत्काल कैश हिट में बदल सकता है। पुन: प्रयोज्य रैपर के साथ कैश-साइड पैटर्न अधिकांश जरूरतों को कवर करता है, रूट-स्तरीय मिडलवेयर संपूर्ण प्रतिक्रियाओं को कैश करता है, और वही रेडिस इंस्टेंस दर सीमित और सत्र को संभालता है। दो कठिन भागों को याद रखें: हमेशा एक टीटीएल सेट करें, और डेटा बदलने पर कैश को अमान्य कर दें। रेडिस विफलताओं को शालीनता से संभालें, और आपका ऐप एक ही समय में तेज़ और अधिक लचीला हो जाता है।
🔗 Share this article
✍️ Leave a Comment