Caching Architectures Using Redis on Dedicated Servers

Updated on Apr 15, 2026
Joey SH
12 MINS READ
Table of Contents
Use Redis Data Caching To Speed Up Processing

In modern applications, speed matters. Whether you’re loading user data, processing transactions, or serving an API, slow database queries can make your system slow. That's where Redis Data Caching comes in. In this tutorial, you will learn how to use Redis Data Caching to Speed Up Processing.

Redis (Remote Dictionary Server) is an in-memory data store that keeps frequently used data in RAM, which allows your app to fetch in microseconds. In this article, we guide you step-by-step to use Redis for caching, from installation to advanced caching patterns and performance tips.

At PerLod Hosting, we provide high-speed web hosting and dedicated servers that are optimized for Redis-based applications.

Why Use Redis for Caching?

Redis is a popular tool because it is fast, flexible, and reliable. Here is why it's most used for caching:

  • In-memory speed: Data is stored in RAM for ultra-fast reads and writes.
  • Supports multiple data types: Strings, Hashes, Lists, Sets, Sorted Sets, Bitmaps, Streams, and more.
  • Built-in TTL (Time-To-Live): Automatically expires old cache data.
  • Smart eviction policies: Remove less useful data first when memory is full.
  • Replication and clustering: Helps scale and add fault tolerance.

Now you can proceed to the next step to install and run Redis.

Installing and Running Redis

You can install Redis in two simple ways: using a system service or Docker. For example, to install Redis on Ubuntu and Debian-based systems, you can run the following commands:

Bash
sudo apt updatesudo apt install redis-server -y

Then, enable and start Redis with:

Bash
sudo systemctl enable redis-serversudo systemctl start redis-server

Once you are done, check that Redis is up and running:

Bash
redis-cli PING

In your output, you must see:

Bash
PONG

Another method is to use Docker, which has an easier setup. To install Redis with Docker, you can use:

Docker
docker run -d --name redis \  -p 6379:6379 \  -v redisdata:/data \  redis:7-alpine \  redis-server --appendonly yes --save "900 1 300 10 60 10000"

This creates a Redis container ready to use.

Basic Redis Configuration For Safety and Performance

At this point, you need to change your Redis settings for safety and better performance. Here is a basic configuration you can make.

Open the Redis configuration file with your desired text editor:

Bash
sudo nano /etc/redis/redis.conf

At the file, adjust the following configs as explained:

Bash
# Network/securitybind 127.0.0.1 ::1            # or your LAN VIP; avoid 0.0.0.0 unless behind a firewallprotected-mode yes# For Redis 6+ prefer ACLs, but you can still set a legacy requirepass:# requirepass STRONG_SECRET_PASSWORD # Memory & evictionmaxmemory 1gb                  # set to ~50–75% of RAM if Redis is cache-onlymaxmemory-policy allkeys-lfu   # great default for general caching# Alternative policies: noeviction, allkeys-lru, volatile-lru, volatile-ttl, allkeys-random, volatile-random # Persistence: if you use Redis as a cache only, you may disable persistence.# If you want warm cache across restarts, keep RDB or AOF.save 900 1save 300 10save 60 10000appendonly yesappendfsync everysec # Observabilityslowlog-log-slower-than 10000  # microseconds = 10msslowlog-max-len 512

Once you are done, save and close the file. Apply changes with:

Bash
sudo systemctl restart redis-server

Tip: If you only use Redis as a temporary cache, disable persistence:

Bash
save ""appendonly no

Use Redis Data Caching to Speed Up Processing

By storing frequently accessed data in Redis, applications can serve responses in milliseconds instead of querying a slower backend. This section introduces key caching techniques that help make your Redis usage efficient, stable, and production-ready.

The first step is to set TTL (expiry). This will keep your data organized and prevent memory issues:

Bash
redis-cli SET user:42 '{"id":42,"name":"username"}' EX 3600redis-cli GET user:42redis-cli TTL user:42redis-cli DEL user:42

Key Rules:

  • Use namespaced keys: app:domain:entity:id. For example, shop:prod:123.
  • Always set the TTL for cache entries (EX seconds or PX milliseconds).

The next step is efficient scans. To safely find keys without crashing your server:

Bash
redis-cli SCAN 0 MATCH "shop:prod:*" COUNT 100

To structure your data for optimal performance: (Hashes: Store Objects Efficiently)

Bash
redis-cli HSET prod:123 name "SSD 1TB" price "79.90"redis-cli HGETALL prod:123redis-cli EXPIRE prod:123 3600

Redis Caching Patterns: Smart Data Loading

Different caching patterns exist to balance data freshness, performance, and complexity. Choosing the right one depends on your application’s read and write patterns. Here are the most popular patterns:

1. Cache-Aside (a.k.a. Lazy Loading): It is the most common and simplest pattern. Your apps check the cache first, and only load from the database if the data is missing.

  • For Python redis-py:
Python
import json, timeimport redisr = redis.Redis(host='localhost', port=6379, decode_responses=True) def get_user(user_id):    key = f"user:{user_id}"    val = r.get(key)    if val is not None:        return json.loads(val), True  # hit    # Miss -> load from DB (pseudo)    user = {"id": user_id, "name": "username"}  # db_get_user(user_id)    r.set(key, json.dumps(user), ex=3600)    return user, False
  • For Node.js ioredis:
JavaScript
const Redis = require("ioredis");const redis = new Redis("redis://127.0.0.1:6379"); async function getUser(id) {  const key = `user:${id}`;  const cached = await redis.get(key);  if (cached) return { data: JSON.parse(cached), hit: true };  const data = { id, name: "username" }; // await dbGetUser(id)  await redis.set(key, JSON.stringify(data), "EX", 3600);  return { data, hit: false };}

This method is good for web applications and is simple to implement. When the cache expires, watch out for Cold misses.

2. Read-Through Cache: It lets your cache library handle the complexity and automatically fetches from the database on cache misses. You can use it when your ORM or cache library supports it.

Pattern is similar to cache-aside but managed by middleware.

3. Write-Through: Write to both cache and database simultaneously. It keeps the cache always fresh, but makes writes slower.

4. Write-Behind (Write-Back): Write to cache first, then sync to the database later. It has fast writes, but with the risk of data loss.

5. Negative caching: Cache "not found" results to avoid repeatedly searching for missing data:

Python
MISS = "__MISS__"def get_product(pid):    key = f"prod:{pid}"    v = r.get(key)    if v is not None:        return None if v == MISS else json.loads(v)    prod = None  # db_get(pid)    if prod is None:        r.set(key, MISS, ex=60)        return None    r.set(key, json.dumps(prod), ex=3600)    return prod

6. Cache stampede protection: Prevent all your cache entries from expiring at the same time, which could overwhelm your database.

  • Randomized TTL jitter like 3600–4200s to prevent mass expiry.
  • Mutex or lock so only one worker repopulates.
Python
def get_with_lock(key, loader, base_ttl=3600):    v = r.get(key)    if v: return v    lock_key = f"lock:{key}"    if r.set(lock_key, "1", nx=True, ex=10):   # acquire        try:            data = loader()            ttl = base_ttl + int(60 * time.time()) % 300  # simple jitter example            r.set(key, data, ex=ttl)            return data        finally:            r.delete(lock_key)    else:        time.sleep(0.1)        return r.get(key)

Redis Atomic Operations and Lua Scripts (Advanced)

In a multi-threaded or distributed environment, race conditions can occur when multiple processes try to access or modify the same data simultaneously. Atomic operations ensure that complex operations happen completely or not at all.

Here is the Built-in atomic command:

SET with NX + EX: The simplest atomic operation, which only sets the key if it doesn't already exist.

Bash
redis-cli SET session:abc 1 EX 1800 NX

When you need to perform multiple operations atomically, Lua scripts are the solution.

Lua example (read-through + TTL):

Bash
redis-cli --eval cache_getset.lua mykey , "payload-json" 3600

The cache_getset.lua:

Bash
local v = redis.call('GET', KEYS[1])if v then return v endredis.call('SET', KEYS[1], ARGV[1], 'EX', ARGV[2])return ARGV[1]

Data Modeling Tips for Redis Caching

Redis supports multiple data types, and choosing the right one for your cache can dramatically affect performance and maintainability. Here are the data modeling tips:

  • Strings: Simple JSON blobs.
  • Hashes: Object with multiple fields.
  • Sets: Unique items (tags, categories).
  • Sorted Sets: Rankings and leaderboards.

Note: Always design key namespaces and TTL strategy per entity.

Redis Eviction Policies: When Memory is Full

Redis stores all data in memory, so when it reaches the configured limit, it must decide what to remove. The eviction policy defines this behavior.

  • noeviction: Don't remove anything (not for caching).
  • allkeys-lru: Remove least recently used keys.
  • allkeys-lfu: Remove least frequently used keys (recommended).
  • volatile-lru / volatile-ttl / volatile-lfu: Remove only keys with TTL.
  • allkeys-random / volatile-random: Random remove.

You can set this setting via the Redis config file:

Bash
sudo nano /etc/redis/redis.conf

For example:

Bash
maxmemory 2gbmaxmemory-policy allkeys-lfu

Measuring Redis Performance: Health Checks

Performance monitoring is essential to ensure Redis continues to meet your latency and throughput goals.

Run a quick benchmark with:

Bash
redis-benchmark -t get,set -q -n 100000 -c 50

Monitor latency with:

Bash
redis-cli --latency

Press Ctrl+C to stop; look at avg/p95.

Check for slow commands:

Bash
redis-cli SLOWLOG GET 10

Redis Cache Invalidation Strategies

Cache invalidation ensures that your cached data reflects real-world changes. Here are some strategies you can use to clear outdated cache:

1. Direct key delete on writes:

Bash
redis-cli DEL user:42

2. Tagging (namespaced prefixes): On bulk invalidation, rotate a versioned prefix:

  • Store a prefix in Redis: prefix:user = v7.
  • Keys become user:v7:42. To invalidate all user cache, set prefix:user = v8.

3. Event-driven invalidation: DB triggers or change streams publish invalidation messages (check Pub/Sub section).

Redis Publish and Subscribe System for Real-time Updates

Redis’s Publish and Subscribe system allows instant broadcasting of messages to multiple subscribers. It is ideal for cache invalidation, event notifications, or live updates.

When combined with your application logic, Pub/Sub enables dynamic cache refreshes or downstream updates triggered by data changes, keeping distributed systems synchronized with minimal latency.

Terminal A (subscriber):

Bash
redis-cli SUBSCRIBE inv

Terminal B (publisher):

Bash
redis-cli PUBLISH inv "invalidate user:42"

Your app can subscribe and DEL or recompute keys accordingly.

Redis Security and Access Control

Securing your Redis deployment is essential to prevent unauthorized access and data breaches. By default, Redis trusts local connections, but in production, you must restrict access to trusted networks, enforce authentication, and encrypt connections.

  • Bind to loopback or to a private VPC/VLAN.
  • Use a firewall like UFW, iptables, or security groups.
  • Redis 6+ ACLs:
Bash
# Inside redis-cli (admin)ACL SETUSER app on >SuperStrongSecret ~app:* +@allACL LISTAUTH app SuperStrongSecret
  • Enable TLS via stunnel, Envoy, or Redis built-in TLS build if required.
  • Avoid exposing Redis to the internet.

High Availability Strategies for Redis

High availability (HA) ensures your Redis service remains operational even during node failures. Redis offers multiple strategies, including simple replication, automatic failover via Sentinel, and horizontal scaling through Clustering.

1. Replication: Replication creates one or more read-only copies of your primary Redis instance. It improves data durability, supports read scaling, and enables quick recovery from primary failures.

Primary redis.conf:

Bash
replica-read-only yes

Replica redis.conf:

Bash
replicaof 10.0.0.10 6379

Check with:

Bash
redis-cli INFO replication

2. Sentinel: Redis Sentinel provides monitoring, automatic failover, and service discovery for Redis deployments. It detects when the primary is unavailable and promotes a replica to take over, minimizing downtime without manual intervention.

Sentinel file sentinel.conf: Three sentinels recommended.

Bash
port 26379sentinel monitor mymaster 10.0.0.10 6379 2sentinel down-after-milliseconds mymaster 5000sentinel failover-timeout mymaster 60000sentinel parallel-syncs mymaster 1

Run with:

Bash
redis-sentinel /etc/redis/sentinel.conf

3. Cluster (Sharding for Scale): Redis Cluster distributes data across multiple nodes to scale horizontally. Each master node handles a subset of keys, and replicas ensure redundancy. It’s the production-ready solution for handling large-scale workloads and high throughput requirements.

Requires 6 nodes, 3 masters with 3 replicas for production:

Bash
# Example (adjust IPs/ports)redis-cli --cluster create \  10.0.0.11:6379 10.0.0.12:6379 10.0.0.13:6379 \  10.0.0.21:6379 10.0.0.22:6379 10.0.0.23:6379 \  --cluster-replicas 1

Clients must be cluster-aware.

Tip: For production use, Redis should run on a reliable and high-performance dedicated server. PerLod offers dedicated Redis-ready servers with SSD storage and private networking, ideal for replication, Sentinel, and cluster setups.

Observability and Maintenance for Redis Performance

Ongoing visibility into Redis performance is essential for stability and optimization. Key metrics to monitor include:

  • INFO: redis-cli INFO or INFO memory and INFO keyspace.
  • Keyspace hits and misses: INFO stats → keyspace_hits and keyspace_misses.
  • Memory: MEMORY STATS, MEMORY USAGE key.
  • Prometheus: deploy redis_exporter.
  • AOF and RDB maintenance: BGREWRITEAOF, BGSAVE.
  • Latency monitoring: LATENCY DOCTOR if enabled.

Example: Redis Caching REST API Responses

To gather everything together, this step shows Redis in action within a FastAPI application. The example shows how to cache REST API responses efficiently, compute deterministic cache keys, set expiration with jitter, and manage cache hits and misses—all essential patterns for real-world caching.

Python: FastAPI with redis-py.

Python
from fastapi import FastAPIimport json, hashlib, aiohttp, asyncioimport redis.asyncio as redis app = FastAPI()r = redis.from_url("redis://127.0.0.1:6379", encoding="utf-8", decode_responses=True) def cache_key(url, params):    raw = url + json.dumps(params, sort_keys=True)    return "api:" + hashlib.sha256(raw.encode()).hexdigest() @app.get("/proxy")async def proxy(url: str):    key = cache_key(url, {})    v = await r.get(key)    if v:  # hit        return json.loads(v)     async with aiohttp.ClientSession() as s:        async with s.get(url, timeout=5) as resp:            data = await resp.json()     # Set with jitter to prevent thundering herds    ttl = 300 + (hash(url) % 60)    await r.set(key, json.dumps(data), ex=ttl)    return data

Load Testing Redis Caching Layer

Before going live, stress-test your caching layer to validate its performance under real-world conditions. You can simulate load using tools like Hey or Bombardier, monitor hit and miss ratios, and measure Redis latency.

Proper testing ensures that caching actually reduces backend load and improves application responsiveness.

Hit your application endpoint with mixed cache hits and misses:

Bash
# Example: bombardier or heyhey -z 30s -c 100 http://localhost:8000/proxy?url=https://api.example.com/data

Monitor Redis:

Bash
redis-cli INFO stats | egrep "keyspace_hits|keyspace_misses"redis-cli --latency

Conclusion

Redis is one of the simplest yet most powerful tools to make your applications lightning-fast. By caching data in memory, you reduce database load, increase speed, and improve user experience. We hope you enjoy "Use Redis Data Caching to Speed Up Processing".

Subscribe to X and Facebook channels to get the latest updates and articles.

For further reading:

Optimize Game Server for Better Performance

Choose a GPU server for Video Editing

How to check I/O latency in Linux?

Redis stores frequently accessed data in memory to reduce the need for slow database queries.

Yes, if you set a TTL or use an eviction policy.

allkeys-lfu is a great default because it keeps the most-used data in memory.