Back to writing

Comprehensive Guide to Redis

Redis is a dynamic in-memory data store renowned for its versatility, commonly serving as a caching mechanism, message broker, and general-purpose data store. Below, we delve into its core features, installation, and usage within a Node.js application.

Key Features of Redis

  1. In-Memory Data Store — Redis excels by storing data in memory, ensuring lightning-fast read and write operations.
  2. Data Structures — Redis supports diverse data structures, including strings, hashes, lists, sets, and sorted sets, providing flexibility for various use cases.
  3. Caching — A prevalent use of Redis is as a cache. By storing frequently accessed data in memory, applications can enhance performance by reducing database load.
  4. Persistence — While primarily operating in-memory, Redis offers options for persisting data to disk, enabling its use as both a database and cache.

Installing Redis

To install Redis on macOS using brew:

brew install redis

Using Redis in a Node.js Application

In a Node.js application, installing the high-performance Redis client, ioredis, is common:

npm install ioredis

Create a .env.local file in the project root for Redis connection information:

# .env.local

REDIS_PORT=6379
REDIS_HOST=localhost

Initializing the Redis Client

Initialize the Redis client in the application, typically in the Lib directory:

import Redis, { RedisOptions } from "ioredis";

export function createRedisInstance() {
  try {
    const options: RedisOptions = {
      port: process.env.REDIS_URL as unknown as number,
      host: process.env.REDIS_HOST as string,
      lazyConnect: true,
      showFriendlyErrorStack: true,
      enableAutoPipelining: true,
      maxRetriesPerRequest: 0,
      retryStrategy: (times: number) => {
        if (times > 3) {
          throw new Error(`[Redis] Could not connect after ${times} attempts`);
        }

        return Math.min(times * 200, 1000);
      },
    };

    const redis = new Redis(options);

    redis.on("error", (error: unknown) => {
      console.warn("[Redis] Error connecting", error);
    });

    return redis;
  } catch (e) {
    throw new Error(`[Redis] Could not create a Redis instance`);
  }
}

const redis = createRedisInstance();
export default redis;

Using Redis Operations

Redis operations are straightforward. Here are some examples:

# Set a key
await redis.set("key", "value");

# Get a key
await redis.get("key");

# Get all keys
await redis.keys("*");

Explore the ioredis documentation for a comprehensive list of operations.

Creating a Simple API Route

Finally, let’s demonstrate Redis in action with a simple API user route in a Next.js application:

import redis from "@/lib/redis";
import { NextApiRequest, NextApiResponse } from "next";

const database = {
  1: "Connor",
  2: "Sarah",
  3: "John",
} as const;

export default async function handler(
  req: NextApiRequest,
  res: NextApiResponse,
) {
  const { id } = req.query;

  // Reader exercise: setup error handling.

  const cachedKey = await redis.get(id.toString());

  if (cachedKey) {
    res.end(
      `Key was retrieved from redis cache: ${cachedKey}\nRedis keys currently stored: ${await redis.keys(
        "*",
      )}`,
    );
    return;
  }

  const user = database[id];

  if (!user) {
    res.status(404).json({ message: "User not found" });
    return;
  }

  const MAX_AGE = 60_000 * 60; // 1 hour
  const EXPIRY_MS = `PX`; // milliseconds

  await redis.set(id.toString(), user, EXPIRY_MS, MAX_AGE);

  res.end(
    `Key was retrieved from Database: ${user}\nRedis keys currently stored: ${await redis.keys(
      "*",
    )}`,
  );
}

Conclusion

Redis proves beneficial for Node.js projects due to its speed and simplicity as an in-memory data store. This guide outlines its utility for caching frequently accessed data, enhancing overall performance by reducing database load. With easy integration into Node.js applications using libraries like ioredis, Redis offers a user-friendly solution for efficient data storage and retrieval in real-world scenarios.