Blog, COLDSURF

About Redis.

When using AWS to set up Redis, there are two main approaches:

  • Using ElastiCache
  • Installing directly on an EC2 instance

In this guide, Iā€™ll cover how to install Redis directly on an EC2 instance.

Installing Redis on Amazon Linux (EC2)

First, update the system with the following command:

sudo yum update -y
# Enable the Extra Packages for Enterprise Linux (EPEL) repository
$ sudo amazon-linux-extras install epel -y
# Install the Remi Repository
$ sudo yum install -y <https://rpms.remirepo.net/enterprise/remi-release-7.rpm>
# Enable the Remi Redis module
$ sudo yum --enablerepo=remi install redis -y
# Start Redis
$ sudo systemctl start redis
# Enable Redis to start on boot
$ sudo systemctl enable redis
# Check Redis status
$ sudo systemctl status redis

Using this method, I installed Redis with yum.

$ redis-server # Alternatively, use redis-cli to connect to Redis on localhost

Allowing External Access to Installed Redis

By default, Redis configurations are located in the /etc/redis.conf file. Open this file with vim or nano and search for the word bind. By default, itā€™s likely set as bind 127.0.0.1. Change this setting to bind 0.0.0.0 to allow access from outside the EC2 instance, if needed.

Setting a Password for Redis

If youā€™ve configured bind to allow access from all IP addresses, setting a password is essential. Open the /etc/redis.conf file again, search for requirepass, and set a password by modifying the requirepass property.

Once done, apply the settings by restarting Redis with:

sudo systemctl restart redis

Configuring Load Balancer or Security Settings

If your EC2 instance is connected to a Load Balancer, youā€™ll need to configure port 6379 as follows:

Step 1: Create a Target Group for Redis

  1. Go to the AWS Management Console and navigate to the EC2 Dashboard.
  2. Under Load Balancing, select Target Groups and click Create target group.
  3. Choose target type: Select Instances.
  4. Target group name: Name your target group, for example, redis-target-group.
  5. Protocol: Choose TCP.
  6. Port: Enter 6379.
  7. VPC: Select the VPC where your Redis EC2 instance is running.
  8. Health checks: Set the protocol to TCP (since Redis doesnā€™t have HTTP endpoints, use TCP for health checks).
  9. Advanced health check settings: Adjust the health check interval, timeout, and thresholds as needed.
  10. Register Targets: Select your Redis EC2 instance, add it to registered targets, and click Create target group.

Step 2: Create a Network Load Balancer (NLB)

  1. In the EC2 Dashboard, go to Load Balancers and click Create Load Balancer.
  2. Choose a load balancer type: Select Network Load Balancer.
  3. Name: Name your load balancer, for example, redis-nlb.
  4. Scheme: Choose Internet-facing (for external access) or Internal (for VPC-only access).
  5. IP address type: Choose IPv4.
  6. Listeners:
      • Change the default listener on TCP port 80 to TCP and 6379 for Redis.
  7. Availability Zones: Select the VPC and the subnets where your Redis instance is running. For multiple availability zones, select the respective subnets.
  8. Click Next.

Step 3: Configure the Load Balancer with the Target Group

  1. Select Target Group: In the Target Group section, choose Select a target group and pick the Redis target group you created earlier.
  2. Click Create Load Balancer.

Step 4: Modify Security Groups

To allow traffic through the load balancer to your Redis instance, make sure both the load balancer and the Redis instance have the proper security group rules.

  1. Load Balancer Security Group: The NLB doesnā€™t need a security group as it operates at the network layer, but ensure your Redis instance allows inbound traffic from the load balancer.
      • In your Redis EC2 instanceā€™s security group, add an inbound rule allowing TCP traffic on port 6379 from the load balancerā€™s IP range.
      • Set the Source to Custom and specify the security group or IP range.
  2. Redis Instance Security Group: Allow inbound traffic on port 6379.
      • Type: Custom TCP Rule
      • Protocol: TCP
      • Port Range: 6379
      • Source: Choose the security group linked to your load balancer, or set it to 0.0.0.0/0 for public access (not recommended for security).

If your EC2ā€™s security settings are simple, opening port 6379 with an IP of 0.0.0.0 will suffice.

Accessing Redis Remotely

First, install the ioredis module:

yarn add ioredis

This guide doesnā€™t cover ioredis in detail, just enough to connect and set key-value pairs. For more details, refer to the official documentation at https://github.com/redis/ioredis.

import Redis from 'ioredis'

const redisClient = new Redis({
  host: process.env.REDIS_URL ?? '', // host URL
  port: process.env.REDIS_PORT ? +process.env.REDIS_PORT : undefined, // port number
  password: process.env.REDIS_PASSWORD ?? '', // Redis password
})

export const redisKeys = {
	// Define key factory for keys youā€™ll use
} as const

export class RedisClient {
  static async get<T>(key: string) {
    try {
      const value = await redisClient.get(key)
      if (!value) {
        return null
      }
      const parsed = JSON.parse(value) as T
      return parsed
    } catch (e) {
      console.error(e)
      return null
    }
  }

  static async set(key: string, value: string, expire?: number) {
    await redisClient.set(key, value)
    if (expire) {
      await redisClient.expire(key, expire)
    }
  }
}

Iā€™ve set up a simple interface class for RedisClient, which can be used in controllers as shown below:

const redisValue = await RedisClient.get<SerializedType[]>(
	redisKeys.SOME_KEY(params) // Use parameters in the key factory for separate keys
)

if (redisValue) {
	// If a value is saved in Redis, return it as is
	return rep.status(200).send(redisValue)
}

// ... Business logic

const dto = await SomeDTO.getById(req.params.id)
const response = dto.serialize()
await RedisClient.set(
	redisKeys.SOME_KEY(params),
	JSON.stringify(response),
	60 * 60 // expiry time
)

// If the value is not in Redis, set it and return
return rep.status(200).send(response)
ā† Go home