Use Redis for Caching PostgreSQL Queries

By Anurag Singh

Updated on Oct 02, 2024

Use Redis for Caching PostgreSQL Queries

In this tutorial, we'll learn how to use Redis for caching PostgreSQL queries.

Redis (Remote Dictionary Server) is a popular in-memory data structure store used as a database, cache, and message broker. This guide provides step-by-step instructions for setting up Redis as a caching layer for web applications to improve database query performance.

Prerequisites

  • A server running Ubuntu 24.04 dedicated server or KVM VPS.
  • Database: MySQL or PostgreSQL (Optional: An application using the database)
  • Basic knowledge of the command line and Linux administration.

Use Redis for Caching PostgreSQL Queries

Step 1: Installing Redis

1.1 Update the system packages

First, update your system packages to ensure you have the latest versions.

sudo apt update && sudo apt upgrade -y

1.2 Install Redis

Next, install Redis using following set of commands (We have copied it from Redis official documentation) :

sudo apt-get install lsb-release curl gpg
curl -fsSL https://packages.redis.io/gpg | sudo gpg --dearmor -o /usr/share/keyrings/redis-archive-keyring.gpg
sudo chmod 644 /usr/share/keyrings/redis-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/redis-archive-keyring.gpg] https://packages.redis.io/deb $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/redis.list
sudo apt-get update
sudo apt-get install redis

1.3 Verify Redis Installation

Check the status of Redis to ensure it is running:

sudo systemctl status redis-server

You should see an output indicating that Redis is active and running.

Step 2: Configure Redis for Caching

By default, Redis is configured to run as a general-purpose key-value store. To optimize Redis for caching, some configuration changes are needed.

2.1 Edit Redis Configuration

Open the Redis configuration file:

sudo nano /etc/redis/redis.conf

2.2 Set Max Memory Usage

Redis will work as a cache by evicting older data when memory is full. To limit Redis memory usage and configure eviction policies:

Find the following line and uncomment it (remove the #):

maxmemory <value>

Set the maximum memory limit, for example, 512MB:

maxmemory 512mb

2.3 Configure Eviction Policy

Redis uses eviction policies to decide how to handle memory limits. Below are the common policies:

  • noeviction: Returns an error when memory limit is reached.
  • allkeys-lru: Removes the least recently used (LRU) key across all keys.
  • volatile-lru: Removes the least recently used (LRU) key with an expiration.

For caching, it’s recommended to use the allkeys-lru policy:

maxmemory-policy allkeys-lru

2.4 Save and Restart Redis

Save the changes and restart Redis:

sudo systemctl restart redis

Integrate Redis and PostgreSQL in a Python Application

To demonstrate how Redis caching works with PostgreSQL, we’ll walk through installing PostgreSQL and setting up Redis as a cache to improve query performance. The steps below will show how to install PostgreSQL, integrate Redis with a Python application, and run a demo to verify successful integration.

Step 1: Install PostgreSQL

1.1 Update the system packages

Start by updating the system packages.

sudo apt update

1.2 Install PostgreSQL

Install PostgreSQL using the package manager:

sudo apt install postgresql postgresql-contrib -y

1.3 Start and Enable PostgreSQL

Make sure the PostgreSQL service is running and enabled on startup.

sudo systemctl start postgresql
sudo systemctl enable postgresql

1.4 Set PostgreSQL Password and Access

Switch to the postgres user to configure the database.

sudo -i -u postgres

Set the password for the postgres user:

psql
ALTER USER postgres PASSWORD 'your_password';
\q

Step 2: Create a Demo Database and Table

Now, create a sample database and table.

2.1 Create a Database

Run the following commands to create a database:

psql
CREATE DATABASE demo_db;
\q

2.2 Create a Table and Insert Data

Connect to the newly created demo_db:

psql -d demo_db

Create a simple table called users:

CREATE TABLE users (
  id SERIAL PRIMARY KEY,
  name VARCHAR(100),
  email VARCHAR(100)
);

Insert some sample data:

INSERT INTO users (name, email) VALUES
('Alice', 'alice@example.com'),
('Bob', 'bob@example.com');

Exit:

\q
exit

Step 3: Set up Python Project

Install the Python virtual environment

apt install python3.12-venv -y

Note: Python version might be different for you. 

Create project directory:

mkdir project && cd project

Create virtual environment and activate it:

python3 -m venv venv
source venv/bin/activate

Install Required Python Libraries

We’ll need the following Python libraries: psycopg2 for PostgreSQL interaction and redis for Redis interaction.

Install them using pip:

pip install psycopg2-binary redis

Python Script to Use Redis Cache with PostgreSQL

Create Python script file. 

nano redis_postgresql_demo.py

Add following Python code that demonstrates caching PostgreSQL query results in Redis.

import psycopg2
import redis
import json

# Connect to PostgreSQL
conn = psycopg2.connect(
    dbname="demo_db",
    user="postgres",
    password="your_password",
    host="localhost"
)

# Create a Redis client
redis_client = redis.StrictRedis(host='localhost', port=6379, db=0)

def get_user_from_db(user_id):
    """Fetch user details from PostgreSQL."""
    cur = conn.cursor()
    cur.execute(f"SELECT * FROM users WHERE id = {user_id};")
    user = cur.fetchone()
    cur.close()
    return user

def get_user(user_id):
    """Fetch user details from Redis cache or PostgreSQL."""
    # Check if the user is in Redis cache
    cache_key = f"user:{user_id}"
    cached_user = redis_client.get(cache_key)
    
    if cached_user:
        print("Fetching from Redis Cache...")
        return json.loads(cached_user)
    else:
        # If not in cache, fetch from PostgreSQL and cache the result
        print("Fetching from PostgreSQL...")
        user = get_user_from_db(user_id)
        if user:
            redis_client.setex(cache_key, 600, json.dumps(user))
        return user

# Example: Fetch user with ID 1
user = get_user(1)
if user:
    print(f"User Details: ID = {user[0]}, Name = {user[1]}, Email = {user[2]}")
else:
    print("User not found")

Save and exit the file.

Step 4: Run the Demo

Run the Python Script: Execute the Python script to verify that Redis is caching the query result. When running the script for the first time, it will fetch the data from PostgreSQL. Subsequent runs will fetch the data from Redis.

python redis_postgresql_demo.py

Output:

On the first run, you should see:

Fetching from PostgreSQL...
User Details: ID = 1, Name = Alice, Email = alice@example.com

On subsequent runs, you should see:

Fetching from Redis Cache...
User Details: ID = 1, Name = Alice, Email = alice@example.com

This confirms that the data is being cached in Redis after the first query from PostgreSQL.

Step 5: Verify Redis Caching

You can verify that the data has been cached in Redis using the redis-cli.

redis-cli

Inside the Redis CLI, check for the cached key:

keys *

You should see the user:1 key in the output, which holds the cached result of the query.

To inspect the value:

get user:1

This will return the cached JSON value of the user data.

Step 6: Best Practices for Redis Caching

Set Expiration for Cached Data: Always set an expiration time to ensure old data is removed and new queries get fresh data.

redis.setex('key', expiration_in_seconds, 'value')

Avoid Caching Too Much Data: Cache only frequent queries to avoid overloading Redis with unnecessary data.

Monitor Cache Hits and Misses: Keep track of how often your application retrieves data from the cache vs. the database to ensure Redis is improving performance.

Step 7: Clean Up (Optional)

Check for all keys:

redis-cli keys '*'

Clear Redis Cache: You can remove all keys from Redis with the following command:

redis-cli flushall

Stop PostgreSQL and Redis:

sudo systemctl stop postgresql
sudo systemctl stop redis

Sample Integrate Redis Caching For PHP, Python, and NodeJS

To use Redis as a cache, your application needs to be configured to connect to Redis. Below are the steps for PHP, Python (Flask/Django), and Node.js applications.

Using Redis in PHP

Install the Redis PHP extension:

sudo apt install php-redis

Configure Redis caching in your PHP application:

$redis = new Redis();

$redis->connect('127.0.0.1', 6379);

// Cache a database query result
$cacheKey = 'user_1_profile';
if ($redis->exists($cacheKey)) {
    $userProfile = $redis->get($cacheKey);
} else {
    // Fetch from the database
    $userProfile = fetchUserProfileFromDB(1);
    // Cache the result for 10 minutes
    $redis->setex($cacheKey, 600, json_encode($userProfile));
}

Using Redis in Python (Flask/Django)

Install the Redis Python client:

pip install redis

Example usage in a Flask or Django app:

import redis
import json

# Connect to Redis
redis_cache = redis.StrictRedis(host='localhost', port=6379, db=0)

cache_key = 'user_1_profile'
cached_profile = redis_cache.get(cache_key)

if cached_profile:
    user_profile = json.loads(cached_profile)
else:
    # Query from the database
    user_profile = fetch_user_profile_from_db(1)
    # Cache for 10 minutes
    redis_cache.setex(cache_key, 600, json.dumps(user_profile))

Using Redis in Node.js

Install the Redis client for Node.js:

npm install redis

Implement Redis caching in a Node.js app:

const redis = require('redis');
const client = redis.createClient();

client.on('error', (err) => {
    console.log('Error ' + err);
});

const cacheKey = 'user_1_profile';
client.get(cacheKey, (err, result) => {
    if (result) {
        const userProfile = JSON.parse(result);
        console.log('Data from cache:', userProfile);
    } else {
        // Fetch from the database
        const userProfile = fetchUserProfileFromDB(1);
        client.setex(cacheKey, 600, JSON.stringify(userProfile));
        console.log('Data from DB and cached');
    }
});

Conclusion

In this tutorial, we've learnt how to use Redis for caching PostgreSQL queries.

Setting up Redis for database caching can significantly reduce the load on your database and improve the performance of your web application. With the steps outlined in this tutorial, you can configure Redis and integrate it into your application for efficient caching. Remember to monitor your Redis instance and configure memory management policies suited to your application’s needs.

By integrating Redis with PostgreSQL, you can reduce the load on your database and speed up query responses by caching frequent database queries. This setup shows how Redis works as a caching layer for PostgreSQL data, fetching results from Redis on repeated queries.