What is Redis?
Redis (REmote DIctionary Server) is an open-source, in-memory key-value data store. Let's break that down:
- In-Memory: Unlike a traditional database like PostgreSQL or MySQL which primarily stores data on a disk (SSD/HDD), Redis keeps the entire dataset in RAM. This makes read and write operations incredibly fast, often taking less than a millisecond.
- Key-Value Store: At its core, Redis is a dictionary. You store a piece of data (a value) and associate it with a unique identifier (a key). Values can be simple strings or more complex data structures like lists, sets, and hashes.
- Data Structure Server: Because it natively supports these complex data types, you can use it for much more than just simple key-value storage.
Think of Redis as your application's short-term, lightning-fast memory, while your SQL database is its long-term, persistent storage.
Use Case 1: Caching
This is the most common use case for Redis. Imagine you have a popular blog post that is read thousands of times per minute. Querying your main database for this post every single time is inefficient and puts a huge load on the database. Caching is the solution.
The most common caching strategy is the cache-aside pattern. The logic is simple:
- Your application needs some data.
- It first checks the Redis cache to see if the data is there (Cache Hit).
- If it is, it returns the data from Redis immediately. Fast!
- If it's not there (Cache Miss), the application queries the primary database (the "source of truth").
- It then stores a copy of that data in the Redis cache with an expiration time (e.g., 5 minutes) before returning it. The next request for this data within 5 minutes will be a cache hit.
Code Snippet: Cache-Aside in a Node.js/Express App
Let's implement this for an endpoint that fetches a user's profile. You'll need express and the redis npm package.
JavaScript
import express from 'express';
import { createClient } from 'redis';
// --- Setup ---
const app = express();
const db = { // A fake database for our example
users: {
'101': { name: 'Alice', bio: 'Software Engineer' },
'102': { name: 'Bob', bio: 'Product Manager' },
}
};
const redisClient = createClient(); // Connects to redis://localhost:6379 by default
await redisClient.connect();
// --- The Route ---
app.get('/users/:id', async (req, res) => {
const { id } = req.params;
const cacheKey = `user:${id}`;
try {
// 1. Check Redis cache first
const cachedUser = await redisClient.get(cacheKey);
if (cachedUser) {
// 2. CACHE HIT: Data found in cache
console.log(`CACHE HIT for ${cacheKey}`);
return res.json(JSON.parse(cachedUser));
}
// 3. CACHE MISS: Data not in cache, query the database
console.log(`CACHE MISS for ${cacheKey}. Querying database...`);
const user = db.users[id];
if (!user) {
return res.status(404).json({ message: 'User not found' });
}
// 4. Store the result in Redis with a 60-second expiration (EX)
await redisClient.set(cacheKey, JSON.stringify(user), { EX: 60 });
return res.json(user);
} catch (error) {
console.error(error);
return res.status(500).json({ message: 'Server error' });
}
});
app.listen(3000, () => console.log('Server running on port 3000'));
Use Case 2: Session Management
When a user logs in, the server creates a "session" to remember them across multiple requests. If you only have one server, you could store this session data in its memory. But what happens when you scale to multiple servers? If a user's request hits a different server, their session won't be found.
Redis provides a perfect solution: a centralized session store. All your server instances can read and write session data to the same Redis database, making your application stateless and easily scalable. Libraries like connect-redis make this simple to integrate with Express.
Use Case 3: Pub/Sub (Publish/Subscribe)
Pub/Sub is a messaging pattern where senders (publishers) send messages to channels, and receivers (subscribers) listen to those channels to receive messages in real-time. The publisher and subscriber don't know about each other; they only know about the channel.
This is great for real-time notifications, chat applications, or triggering actions across different microservices.
Code Snippet: Simple Redis Pub/Sub
You would run these two scripts in separate terminals.
publisher.js:
JavaScript
import { createClient } from 'redis';
const client = createClient();
await client.connect();
async function publishMessage() {
const message = `Hello from the publisher! Time: ${new Date().toLocaleTimeString()}`;
// Publish the message to the 'news' channel
await client.publish('news', message);
console.log(`Published: ${message}`);
}
setInterval(publishMessage, 3000); // Publish a new message every 3 seconds
subscriber.js:
JavaScript
import { createClient } from 'redis';
const client = createClient();
await client.connect();
// Subscribe to the 'news' channel
await client.subscribe('news', (message, channel) => {
console.log(`Received message from channel '${channel}': ${message}`);
});
console.log("Subscriber is listening to the 'news' channel...");
When you run both, you'll see the subscriber printing messages in real-time as the publisher sends them.