NodeJs core is the speed with respect to execution of async
tasks, however there are ways to improve the response time further by using
Redis Cache. I would try to get into concept of Caching and approach to
implementation.
Redis is an open
source (BSD licensed), in-memory data structure store, used as a database,
cache and message broker. It supports strings, hashes, lists, sets, sorted sets
with range queries, bitmaps, hyperloglogs, geospatial indexes with radius
queries and streams. Redis has built-in replication, Lua scripting, LRU
eviction, transactions and different levels of on-disk persistence, and
provides high availability via Redis Sentinel and automatic partitioning with Redis
Cluster.
What is Caching?
Caching is the process of storing data in a temporary data
store where data is kept for later use. This temporary data store is called Cache.
A cache as a data store is easier for the client (or server)
to reach, as opposed to a permanent data store that might be located on a
different service, which takes more time and resources to reach (a database or
an external API endpoint).
First step in application optimization is implementation of caching.
Caching involves storing data in a high performance store (many times
temporarily) so such data can be retrieved faster at a later time. Redis is an
efficient key-value data store that has become a preferred choice for caching. Redis
holds edge over other options because of the number of data structures it
supports — such as strings, hashes, lists, sets, and so on. This provides lot
of flexibility!
Plumbing Node.JS and
Redis
Let’s first install the Redis to understand the impact of
using it as an in-memory data structure for caching on a node server. On
InstallationRedis server is started, it runs on default port 6379.
Here, we will fetch the country codes from the existing
application that seldom changes and cache them on the node server. To use Redis
for caching, we will need Redis module (Redis client) in the Node.JS
application that will help in connecting with the Redis server.
The Redis client would help in storing and obtaining the
data from the Redis cache.
When the data request is made by the Node.JS app, the
products API before moving to the Node server to obtain the data, at first
check the data in the Redis. In case, the data is available in the Redis, then
it’s fetched from the memory and sent as a response to the request. Otherwise,
products API move to the “some_other_domain” to fetch the data and from where
the response is firstly cached in the Redis and then send as a response to the
request.
This way the response time get drastically reduced.
In Node.JS app, when
1000 records are fetched from the legacy application, it took 8 seconds.
When the requested
data is cached on Redis and again requested, the response time reduced to 50
milliseconds.
Furthermore, if database result sets are cached in Redis,
then APIs performance would also increase. The cache can be automatically
cleared by setting its expiration time with the ‘setex’ method.
Epilogue
Leveraging the power Redis, the Node.JS applications can
create a major breakthrough for enterprises. The strong caching layer of Redis
is making the apps respond quickly.
Aforementioned instance elaborated the impact of Redis on
Node.JS app that needs no explanation.
Although Redis has a memory limit where the data equivalent
to the drive capacity can be stored. Also, Redis is worth to use when access to
loads of data is barely needed, but in case, frequent access is needed, then it
proves to be quite expensive.
Redis is a magic bullet that must be used with Node.JS app
strategically depending upon the type of data and access you need.
Example:
We will make a
comparison of 2 pieces of code from Node.js. The following is when we try to
retrieve data from the Google Book API, without put Redis on the endpoint.
Node.Js without Redis
:
- ‘usestrict';
- //Define all dependencies needed
- constexpress=require('express');
- constresponseTime=require('response-time')
- constaxios=require('axios');
- //Load Express Framework
- var app =express();
- //Create a middleware that adds a X-Response-Time header to responses.
- app.use(responseTime());
- constgetBook= (req, res) => {
- letisbn=req.query.isbn;
- leturl=`https://www.googleapis.com/books/v1/volumes?q=isbn:${isbn}`;
- axios.get(url)
- .then(response=> {
- let book =response.data.items
- res.send(book);
- })
- .catch(err=> {
- res.send('The book you are looking for is not found !!!');
- });
- };
- app.get('/book', getBook);
- app.listen(3000, function() {
- console.log('Your node is running on port 3000 !!!')
- });
Node.Js with Redis :
- 'use strict';
- //Define all dependencies needed
- constexpress=require('express');
- constresponseTime=require('response-time')
- constaxios=require('axios');
- constRedis=require('Redis');
- constclient=Redis.createClient();
- //Load Express Framework
- var app =express();
- //Create a middleware that adds a X-Response-Time header to responses.
- app.use(responseTime());
- constgetBook= (req, res) => {
- letisbn=req.query.isbn;
- leturl=`https://www.googleapis.com/books/v1/volumes?q=isbn:${isbn}`;
- returnaxios.get(url)
- .then(response=> {
- let book =response.data.items;
- // Set the string-key:isbn in our cache. With he contents of the cache : title
- // Set cache expiration to 1 hour (60 minutes)
- client.setex(isbn, 3600, JSON.stringify(book));
- res.send(book);
- })
- .catch(err=> {
- res.send('The book you are looking for is not found !!!');
- });
- };
- constgetCache= (req, res) => {
- letisbn=req.query.isbn;
- //Check the cache data from the server Redis
- client.get(isbn, (err, result) => {
- if (result) {
- res.send(result);
- } else {
- getBook(req, res);
- }
- });
- }
- app.get('/book', getCache);
- app.listen(3000, function() {
- console.log('Your node is running on port 3000 !!!')
- });
You can see, the
above code explains that Redis will store the cache data of with unique key
value that we have specified, using this function:
client.setex (isbn,
3600, JSON.stringify(book));
And take the cache
data using the function below:
client.get(isbn,
(err, result) => {
if (result) {
res.send (result);
} else {
getBook (req, res);
}
});
if (result) {
res.send (result);
} else {
getBook (req, res);
}
});
This is the result of
testing of both codes. If we don’t use Redis as cache, it takes at least
908.545 ms
Very different, when
node js use Redis. Look at this, it is very fast, it only takes 0.621 ms to
retrieve data at the same endpoint
Conclusion:
I know there are
still many ways to improve and speed up performance on Node.js and only one way
above, I think not enough to make your Node.js run perfectly. Please let me
know another way, by filling in the comments.