Redis is an open-source, in-memory data structure store that functions as a database, cache, message broker, and streaming engine. Its ability to serve data directly from RAM makes it extraordinarily fast, with typical response times under one millisecond. This guide walks you through deploying Redis on Ubuntu Server, configuring it for production workloads, securing it against common threats, and monitoring its performance with built-in tools.
Prerequisites
Before you begin, make sure you have:
- Ubuntu Server 20.04, 22.04, or 24.04
- Terminal access with sudo privileges
- At least 1 GB of available RAM (more for production datasets)
- Basic familiarity with the Linux command line
- A firewall configured to restrict access (see our UFW guide)
What Is Redis?
Redis stands for Remote Dictionary Server. Created by Salvatore Sanfilippo in 2009, it has grown into one of the most widely used in-memory data stores in the world. Unlike traditional databases that read and write to disk, Redis keeps the entire dataset in memory, which allows it to deliver sub-millisecond latency for both read and write operations.
Key characteristics of Redis:
- In-memory storage — all data lives in RAM for maximum speed
- Rich data structures — supports strings, hashes, lists, sets, sorted sets, streams, and more
- Optional persistence — can write data to disk for durability
- Replication — supports master-replica architecture for high availability
- Atomic operations — all commands are executed atomically
- Pub/Sub messaging — built-in publish/subscribe system for real-time communication
- Lua scripting — execute server-side scripts for complex operations
Redis Use Cases
Redis excels in scenarios where speed is critical:
Caching layer: Place Redis between your application and primary database to serve frequently requested data from memory. This reduces database load and improves response times dramatically.
Session storage: Store user sessions in Redis instead of disk-based stores. This enables session sharing across multiple application servers and provides fast read/write access.
Message queues: Use Redis lists or streams as lightweight message queues for asynchronous task processing. Workers can consume messages reliably using blocking pops or consumer groups.
Pub/Sub messaging: Broadcast real-time events to multiple subscribers. Common for chat applications, live notifications, and real-time dashboards.
Rate limiting: Implement API rate limiting using Redis counters with automatic expiration. The atomic increment and TTL features make this straightforward.
Leaderboards and rankings: Sorted sets provide natural support for ranked data with O(log N) insertion and retrieval by score.
Installing Redis on Ubuntu
The recommended approach is to install Redis from the official APT repository to get the latest stable version.
Add the Official Redis Repository
sudo apt update
sudo apt install -y lsb-release curl gpg
curl -fsSL https://packages.redis.io/gpg | sudo gpg --dearmor -o /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 update
Install Redis
sudo apt install -y redis-server
Verify the Installation
redis-cli ping
You should receive:
PONG
Check the installed version:
redis-server --version
Check the service status:
sudo systemctl status redis-server
Enable Redis to start on boot:
sudo systemctl enable redis-server
Configuration Basics
The main Redis configuration file is located at /etc/redis/redis.conf. Before making changes, create a backup:
sudo cp /etc/redis/redis.conf /etc/redis/redis.conf.backup
Open the configuration file:
sudo nano /etc/redis/redis.conf
Network Binding
By default, Redis binds to 127.0.0.1 (localhost only). For a caching layer accessed by local applications, this is the safest setting:
bind 127.0.0.1 ::1
If remote clients need access, add the server’s private IP:
bind 127.0.0.1 192.168.1.100
Warning: Never bind Redis to
0.0.0.0on a public-facing server without proper authentication and firewall rules. Exposed Redis instances are a frequent target for automated attacks.
Port Configuration
The default port is 6379. Change it if you want to reduce automated scanning:
port 6379
Maximum Memory
Set a hard memory limit to prevent Redis from consuming all system RAM:
maxmemory 256mb
Adjust this value based on your server’s available memory. A common rule is to allocate no more than 75% of total RAM to Redis if it is the primary workload on the server.
Eviction Policies
When Redis reaches the maxmemory limit, it uses an eviction policy to decide which keys to remove. Set the policy with:
maxmemory-policy allkeys-lru
Available eviction policies:
| Policy | Description |
|---|---|
noeviction | Return errors when memory limit is reached (default) |
allkeys-lru | Evict least recently used keys from all keys |
allkeys-lfu | Evict least frequently used keys from all keys |
volatile-lru | Evict least recently used keys with an expiration set |
volatile-lfu | Evict least frequently used keys with an expiration set |
allkeys-random | Evict random keys from all keys |
volatile-random | Evict random keys with an expiration set |
volatile-ttl | Evict keys with the nearest expiration time |
For a general-purpose cache, allkeys-lru is the most common choice. For workloads where access frequency matters more than recency, use allkeys-lfu.
After modifying the configuration, restart Redis:
sudo systemctl restart redis-server
Persistence Options
Redis provides two mechanisms to persist data to disk.
RDB Snapshots
RDB creates point-in-time snapshots at configured intervals. This is enabled by default:
save 3600 1 300 100 60 10000
This means:
- Save if at least 1 key changed in 3600 seconds (1 hour)
- Save if at least 100 keys changed in 300 seconds (5 minutes)
- Save if at least 10000 keys changed in 60 seconds (1 minute)
The snapshot file is stored at:
dbfilename dump.rdb
dir /var/lib/redis
Advantages of RDB:
- Compact single-file representation of your data
- Perfect for backups and disaster recovery
- Minimal performance impact during normal operations
- Faster restarts compared to AOF
Disadvantages of RDB:
- Data loss between snapshots (up to several minutes)
- Fork operation can be slow on large datasets
AOF (Append Only File)
AOF logs every write operation for better durability:
appendonly yes
appendfilename "appendonly.aof"
Configure the sync policy:
# appendfsync always # Sync after every write (safest, slowest)
appendfsync everysec # Sync once per second (recommended)
# appendfsync no # Let the OS handle syncing (fastest, least safe)
Advantages of AOF:
- Better durability (at most 1 second of data loss with
everysec) - Append-only format is corruption-resistant
- Automatically rewrites to compact the log
Disadvantages of AOF:
- Larger file size compared to RDB
- Slower restarts for large datasets
Using Both
For maximum data safety, enable both RDB and AOF:
save 3600 1 300 100 60 10000
appendonly yes
appendfsync everysec
When both are enabled, Redis uses the AOF file to restore data on startup since it is typically more complete.
Security Hardening
An unsecured Redis instance is a significant security risk. Apply the following measures for production deployments.
Set a Password
Configure authentication with a strong password:
requirepass your-very-strong-password-here
Clients must authenticate before running commands:
redis-cli
AUTH your-very-strong-password-here
Or connect with the password inline:
redis-cli -a your-very-strong-password-here
Rename Dangerous Commands
Disable or rename commands that could cause damage:
rename-command FLUSHDB ""
rename-command FLUSHALL ""
rename-command DEBUG ""
rename-command CONFIG "ADMIN_CONFIG_b4f8e2a1"
Setting a command to an empty string "" disables it entirely. Renaming it to a long random string makes it accessible only to administrators who know the new name.
Restrict Network Access
Always bind Redis to specific interfaces and use a firewall:
bind 127.0.0.1 192.168.1.100
protected-mode yes
Add a UFW rule to restrict Redis access:
sudo ufw allow from 192.168.1.0/24 to any port 6379
Enable TLS (Redis 6+)
For encrypted connections, configure TLS:
tls-port 6380
port 0
tls-cert-file /etc/redis/tls/redis.crt
tls-key-file /etc/redis/tls/redis.key
tls-ca-cert-file /etc/redis/tls/ca.crt
Generate certificates for testing:
sudo mkdir -p /etc/redis/tls
sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout /etc/redis/tls/redis.key \
-out /etc/redis/tls/redis.crt \
-subj "/CN=redis-server"
sudo cp /etc/redis/tls/redis.crt /etc/redis/tls/ca.crt
sudo chown redis:redis /etc/redis/tls/*
Connect with TLS:
redis-cli --tls --cert /etc/redis/tls/redis.crt --key /etc/redis/tls/redis.key --cacert /etc/redis/tls/ca.crt -p 6380
Disable the Default User (Redis 6+ ACLs)
Redis 6 introduced Access Control Lists for fine-grained permissions:
redis-cli
ACL SETUSER admin on >strong-password ~* +@all
ACL SETUSER default off
This creates an admin user with full access and disables the default user.
Data Types and Operations
Redis supports several data structures, each optimized for specific use cases.
Strings
The most basic type. Store text, numbers, or serialized data:
SET user:1:name "Alice"
GET user:1:name
# "Alice"
SET counter 100
INCR counter
# 101
SET session:abc123 "session_data" EX 3600
# Expires in 3600 seconds
Hashes
Store objects as field-value pairs:
HSET user:1 name "Alice" email "alice@example.com" age 30
HGET user:1 name
# "Alice"
HGETALL user:1
# 1) "name"
# 2) "Alice"
# 3) "email"
# 4) "alice@example.com"
# 5) "age"
# 6) "30"
Lists
Ordered collections (linked lists) ideal for queues:
LPUSH tasks "send_email"
LPUSH tasks "process_payment"
RPOP tasks
# "send_email"
LRANGE tasks 0 -1
# 1) "process_payment"
Sets
Unordered collections of unique elements:
SADD tags:post:1 "redis" "caching" "nosql"
SMEMBERS tags:post:1
# 1) "redis"
# 2) "caching"
# 3) "nosql"
SISMEMBER tags:post:1 "redis"
# 1
Sorted Sets
Sets ordered by a score, perfect for leaderboards:
ZADD leaderboard 100 "player1" 250 "player2" 175 "player3"
ZREVRANGE leaderboard 0 -1 WITHSCORES
# 1) "player2"
# 2) "250"
# 3) "player3"
# 4) "175"
# 5) "player1"
# 6) "100"
ZRANK leaderboard "player3"
# 1
Memory Management and Eviction Policies
Effective memory management is critical for Redis performance and stability.
Monitoring Memory Usage
redis-cli INFO memory
Key metrics to watch:
| Metric | Description |
|---|---|
used_memory | Total bytes allocated by Redis |
used_memory_human | Human-readable used memory |
used_memory_rss | Resident Set Size (actual RAM used) |
used_memory_peak | Peak memory usage |
mem_fragmentation_ratio | Ratio of RSS to used_memory |
A mem_fragmentation_ratio significantly above 1.5 indicates memory fragmentation. Values below 1.0 mean Redis is swapping to disk, which severely degrades performance.
Reducing Memory Usage
Use shorter key names where practical:
# Instead of
SET user:session:authentication:token:abc123 "data"
# Use
SET u:s:t:abc123 "data"
Set TTL on cached keys to ensure stale data is removed:
SET cache:product:42 "product_data" EX 300
Use hashes for small objects — Redis optimizes small hashes with ziplist encoding:
HSET user:1 name "Alice" email "alice@example.com"
Enable lazy freeing to avoid blocking during large key deletions:
lazyfree-lazy-eviction yes
lazyfree-lazy-expire yes
lazyfree-lazy-server-del yes
Memory Defragmentation (Redis 4+)
Enable active defragmentation to reclaim fragmented memory:
activedefrag yes
active-defrag-ignore-bytes 100mb
active-defrag-threshold-lower 10
active-defrag-threshold-upper 100
Monitoring with redis-cli and INFO Command
Redis provides several built-in tools for monitoring.
The INFO Command
The INFO command returns comprehensive server information:
redis-cli INFO
Request specific sections:
redis-cli INFO server
redis-cli INFO memory
redis-cli INFO stats
redis-cli INFO replication
redis-cli INFO clients
redis-cli INFO keyspace
Real-Time Monitoring
Watch all commands processed by Redis in real time:
redis-cli MONITOR
Caution: The MONITOR command introduces overhead and should not be left running in production. Use it for debugging sessions only.
Slow Log
Identify commands that exceed a specified execution time:
redis-cli SLOWLOG GET 10
Configure the slow log threshold (in microseconds):
slowlog-log-slower-than 10000
slowlog-max-len 128
This logs any command taking longer than 10 milliseconds.
Client Connections
List all connected clients:
redis-cli CLIENT LIST
Check the total number of connections:
redis-cli INFO clients
Key client metrics:
connected_clients:15
blocked_clients:0
maxclients:10000
Latency Monitoring
Enable latency monitoring and measure it:
redis-cli CONFIG SET latency-monitor-threshold 100
redis-cli LATENCY LATEST
redis-cli LATENCY HISTORY event-name
Redis as a Session Store
Redis is an excellent choice for storing application sessions, enabling session sharing across multiple servers.
Node.js Example with Express
const express = require('express');
const session = require('express-session');
const RedisStore = require('connect-redis').default;
const { createClient } = require('redis');
const redisClient = createClient({
url: 'redis://127.0.0.1:6379',
password: 'your-redis-password'
});
redisClient.connect();
const app = express();
app.use(session({
store: new RedisStore({ client: redisClient }),
secret: 'your-session-secret',
resave: false,
saveUninitialized: false,
cookie: {
secure: true,
httpOnly: true,
maxAge: 1800000 // 30 minutes
}
}));
app.get('/', (req, res) => {
req.session.views = (req.session.views || 0) + 1;
res.send(`Views: ${req.session.views}`);
});
app.listen(3000, () => console.log('Server running on port 3000'));
Python Example with Flask
from flask import Flask, session
from flask_session import Session
import redis
app = Flask(__name__)
app.config['SESSION_TYPE'] = 'redis'
app.config['SESSION_REDIS'] = redis.Redis(
host='127.0.0.1',
port=6379,
password='your-redis-password'
)
app.config['SESSION_PERMANENT'] = True
app.config['PERMANENT_SESSION_LIFETIME'] = 1800 # 30 minutes
Session(app)
@app.route('/')
def index():
session['views'] = session.get('views', 0) + 1
return f"Views: {session['views']}"
if __name__ == '__main__':
app.run()
Essential redis-cli Commands Reference
| Command | Description |
|---|---|
redis-cli ping | Test server connectivity |
redis-cli INFO | Display server information and statistics |
redis-cli INFO memory | Display memory usage details |
redis-cli MONITOR | Watch all commands in real time |
redis-cli DBSIZE | Return the number of keys in the current database |
redis-cli KEYS pattern | Find keys matching a pattern (use with caution in production) |
redis-cli SCAN 0 MATCH pattern COUNT 100 | Iteratively scan keys (production-safe alternative to KEYS) |
redis-cli SET key value EX seconds | Set a key with expiration |
redis-cli GET key | Retrieve the value of a key |
redis-cli DEL key | Delete one or more keys |
redis-cli TTL key | Check remaining time-to-live of a key |
redis-cli EXPIRE key seconds | Set a timeout on a key |
redis-cli FLUSHDB | Remove all keys from the current database |
redis-cli SLOWLOG GET 10 | View the 10 most recent slow queries |
redis-cli CLIENT LIST | List all connected clients |
redis-cli CONFIG GET maxmemory | Retrieve a configuration parameter |
redis-cli CONFIG SET maxmemory 512mb | Change a configuration parameter at runtime |
redis-cli BGSAVE | Trigger a background RDB snapshot |
redis-cli BGREWRITEAOF | Trigger an AOF rewrite |
redis-cli SHUTDOWN SAVE | Stop the server and save data to disk |
Troubleshooting
Redis Fails to Start
Check the logs for errors:
sudo journalctl -u redis-server -n 50
sudo cat /var/log/redis/redis-server.log
Common causes:
- Syntax error in
redis.conf— validate the configuration file - Port already in use — check with
sudo ss -tlnp | grep 6379 - Insufficient memory — verify available RAM with
free -h
High Memory Usage
redis-cli INFO memory
redis-cli MEMORY DOCTOR
If mem_fragmentation_ratio is above 1.5:
- Enable active defragmentation
- Restart Redis to reclaim fragmented memory
If used_memory is near maxmemory:
- Review and adjust the eviction policy
- Set TTL values on cache keys
- Increase the
maxmemorylimit
Connection Refused Errors
Verify Redis is listening on the expected interface:
sudo ss -tlnp | grep redis
Check the bind directive in redis.conf and ensure your firewall allows connections:
sudo ufw status | grep 6379
Slow Performance
Investigate with the slow log:
redis-cli SLOWLOG GET 25
Check for large keys that may be blocking:
redis-cli --bigkeys
Avoid using KEYS * in production. Use SCAN instead:
redis-cli SCAN 0 MATCH "user:*" COUNT 100
Persistence Errors
If RDB snapshots fail:
redis-cli INFO persistence
Look for rdb_last_bgsave_status:err. Common fixes:
- Ensure the Redis data directory is writable:
sudo chown redis:redis /var/lib/redis - Verify sufficient disk space:
df -h /var/lib/redis - Check overcommit settings:
sudo sysctl vm.overcommit_memory=1
Summary
Redis is a powerful in-memory data store that can dramatically improve your application’s performance when used as a caching layer, session store, or message broker. By properly configuring memory limits, eviction policies, persistence, and security settings, you can run Redis reliably in production environments.
Key takeaways:
- Install Redis from the official repository for the latest stable version
- Always set
maxmemoryand an appropriate eviction policy to prevent uncontrolled memory growth - Choose your persistence strategy based on durability requirements — RDB for periodic snapshots, AOF for near-real-time durability, or both
- Harden Redis with password authentication, network binding restrictions, and renamed dangerous commands
- Monitor performance with
INFO,SLOWLOG, andredis-cli --bigkeysto catch issues early - Use
SCANinstead ofKEYSin production to avoid blocking the server
For a comprehensive server security setup, see our guides on UFW Firewall Configuration and the Linux Server Security Checklist.