Introduction to Redis and Caching with Node.js
Prathamesh More
Posted on March 22, 2021
What is Redis?
Redis is an open-source, in-memory data structure store, used as a NoSQL database for the cache to improve the overall response rate for most frequently requested data.
In this blog, we will develop Notes Taking App API, We will implement two feature,
- Take a note from the user.
- Return a note back to the user.
But here will use Redis, to cache note. If the user requests the same note frequently, we will return notes stored in Redis.
REST API Routes
POST => /api/notes => Create notes
GET => /api/notes/:id => Get a note
Software Requirements
Let's begin,
Install the required packages on your local machine:
npm install express body-parser mongoose redis --save
Set up Redis database with Upstash,
Upstash is a serverless database for Redis, with servers/instances, you pay-per-hour or a fixed price. With Serverless, you pay per-request.
This means you're not charged when the database isn't in use. Upstash configures and manages the database for you.
Let's start with creating an account on Upstash,
Now set up database instance,
Create a simple server and connect to the MongoDB database:
const express = require('express');
const mongoose = require('mongoose');
const bodyParser = require('body-parser');
const redis = require('redis');
const app = express();
app.use(bodyParser.json());
mongoose.connect('mongodb://localhost:27017/', {
dbName: 'notes',
useNewUrlParser: true,
useUnifiedTopology: true
}, err => err ? console.log(err) : console.log('Connected to database'));
app.listen(3000, () => console.log('Server running at port 3000'));
Now connect to the Redis server using the configuration provided by Upstash:
//Redis connection
const redis = require("redis");
var client = redis.createClient({
host: "eu1-capital-cattle-31290.upstash.io",
port: "31290",
password: "YOUR_REDIS_PASSWORD",
});
client.on("error", function (err) {
throw err;
});
Mongoose Model:
//Mongoose Model
const NoteSchema = new mongoose.Schema({
title: String,
note: String,
});
const note = mongoose.model("Note", NoteSchema);
Now implement routes for API
Get a note from the user and store it Redis and MongoDB:
//Create notes
app.post("/api/notes", (req, res, next) => {
const { title, note } = req.body;
const _note = new Note({
title: title,
note: note,
});
_note.save((err, note) => {
if (err) {
return res.status(404).json(err);
}
//Store in Redis
client.setex(note.id, 60, JSON.stringify(note), (err, reply) => {
if (err) {
console.log(err);
}
console.log(reply);
});
return res.status(201).json({
message: "Note has been saved",
note: note,
});
});
});
Take look here in the code, we used a method setex
to store data in Redis.
This method takes 4 parameters
id
: Unique ID must be provided to store data. It must be a string.seconds
: Expiry time in seconds as a number.value
: Actual data to store in Redis. It must be a string. So we are serializingobject
intostring
.callback
: Callback takes two parameterserr
andreply
.
Now retrieve data, first, we have to check in Redis for data, if data is not available in Redis then we have to make a query in the database.
For that, we have to write middleware that checks the requested data in Redis.
Middleware:
const isCached = (req, res, next) => {
const { id } = req.params;
//First check in Redis
client.get(id, (err, data) => {
if (err) {
console.log(err);
}
if (data) {
const reponse = JSON.parse(data);
return res.status(200).json(reponse);
}
next();
});
};
In the above middleware, we used get()
method to retrieve existing data from Redis. get(id, callback())
.
Here we parsed string
back to the object
.
Now use this middleware on get
request:
app.get("/api/notes/:id", isCached, (req, res, next) => {
const { id } = req.params;
Note.findById(id, (err, note) => {
if (err) {
return res.status(404).json(err);
}
return res.status(200).json({
note: note,
});
});
});
First time retrieves data. It took 11ms
Next, we retried to get data, It took 5ms
Code
const express = require('express');
const mongoose = require('mongoose');
const bodyParser = require('body-parser');
const redis = require('redis');
const app = express();
app.use(bodyParser.json());
//Redis connection
var client = redis.createClient({
host: "eu1-capital-cattle-31290.upstash.io",
port: "31290",
password: "YOUR_REDIS_PASSWORD",
});
client.on("error", function (err) {
throw err;
});
//MongoDB connection
mongoose.connect('mongodb://localhost:27017/', {
dbName: 'notes',
useNewUrlParser: true,
useUnifiedTopology: true
}, err => err ? console.log(err) : console.log('Connected to database'));
//Mongoose Model
const NoteSchema = new mongoose.Schema({
title: String,
note: String
});
const Note = mongoose.model('Note', NoteSchema);
//Create notes
app.post('/api/notes', (req, res, next) => {
const { title, note } = req.body;
const _note = new Note({
title: title,
note: note
});
_note.save((err, note) => {
if (err) {
return res.status(404).json(err);
}
//Store in Redis
client.setex(note.id, 60, JSON.stringify(note), (err, reply) => {
if (err) {
console.log(err);
}
console.log(reply);
});
return res.status(201).json({
message: 'Note has been saved',
note: note
});
})
});
const isCached = (req, res, next) => {
const { id } = req.params;
//First check in Redis
client.get(id, (err, data) => {
if (err) {
console.log(err);
}
if (data) {
const reponse = JSON.parse(data);
return res.status(200).json(reponse);
}
next();
});
}
app.get('/api/notes/:id', isCached, (req, res, next) => {
const { id } = req.params;
Note.findById(id, (err, note) => {
if (err) {
return res.status(404).json(err);
}
return res.status(200).json({
note: note
});
});
});
app.listen(3000, () => console.log('Server running at port 3000'));
Check out Upstash for production: https://upstash.com/
Posted on March 22, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.