Redis Installation and Setup
Redis 5.0+ requires GCC 9.0 or higher for compilation.
# Download and extract
wget http://download.redis.io/releases/redis-3.2.12.tar.gz
tar xzf redis-3.2.12.tar.gz
mv redis-3.2.12 /data/redis
# Build from source
cd /data/redis
make
# Configure environment
vim /etc/profile
export PATH=/data/redis/src:$PATH
source /etc/profile
# Launch server
redis-server &
# Test connection
redis-cli
127.0.0.1:6379> set counter 10
OK
127.0.0.1:6379> get counter
10
Basic Configuration
mkdir /data/6379
cat > /data/6379/redis.conf <<'EOF'
daemonize yes
port 6379
logfile /data/6379/redis.log
dir /data/6379
dbfilename dump.rdb
EOF
redis-cli shutdown
redis-server /data/6379/redis.conf
netstat -lnp|grep 6379
Configuration Parameters
| Parameter | Description |
|---|---|
| daemonize | Run in background (yes/no) |
| port | Listening port (default: 6379) |
| logfile | Log file location |
| dir | Data persistence directory |
| dbfilename | RDB snapshot filename |
redis-cli
127.0.0.1:6379> set username john
OK
127.0.0.1:6379> get username
john
Systemd Service Configuration
[Unit]
Description=Redis
After=network.target
[Service]
ExecStart=/opt/redis/src/redis-server /etc/redis/redis.conf --daemonize no
ExecStop=/opt/redis/src/redis-cli -h 127.0.0.1 -p 6379 shutdown
[Install]
WantedBy=multi-user.target
Save as /lib/systemd/system/redis.service
Service Configuration File
# /etc/redis/redis.conf
daemonize yes
port 6379
logfile /var/log/redis/redis.log
dir /data/redis
dbfilename dump.rdb
mkdir -p /data/redis/ /var/log/redis/
Security Configuration
Redis enables protected mode by default, restricting access to localhost only.
Bind to Specific IPs
vim /data/6379/redis.conf
bind 10.0.0.51 127.0.0.1
Set Authentication Password
vim /data/6379/redis.conf
requirepass mysecretpass
Authentication Methods
# Method 1: Password in command
redis-cli -a mysecretpass
127.0.0.1:6379> set username john
OK
127.0.0.1:6379> exit
# Method 2: Interactive auth
redis-cli
127.0.0.1:6379> auth mysecretpass
OK
127.0.0.1:6379> set x y
# Remote authentication
redis-cli -a mysecretpass -h 10.0.0.51 -p 6379
10.0.0.51:6379> set data 2
OK
Runtime Configuration Management
CONFIG GET *
CONFIG GET requirepass
CONFIG GET r*
CONFIG SET requirepass newpassword
Data Persistence
Redis provides two persistence mechanisms: RDB and AOF.
RDB Persistence
Creates point-in-time snapshots at configured intervals.
Advantages: Fast backup, ideal for disaster recovery; master-replica sync depends on this mechanism.
Disadvantages: Potential data loss between snapshots.
vim /data/6379/redis.conf
dir /data/6379
dbfilename dump.rdb
save 900 1
save 300 10
save 60 10000
Configuration meanings:
- 1 change within 900 seconds (15 minutes)
- 10 changes within 300 seconds (5 minutes)
- 10000 changes within 60 seconds
AOF Persistence
Records all write operations as an append-only log file.
Advantages: Maximum data safety, similar to MySQL binary logging.
Disadvantages: Larger log files, potentially slower performance.
vim /data/6379/redis.conf
appendonly yes
appendfsync everysec
Sync strategies:
always: Sync after every commandeverysec: Sync once per second (default)no: Let the OS handle syncing
Interview summary: RDB uses snapshots for faster backup; AOF logs operations sequentially for maximum data integrity.
Data Types
String - String values
Hash - Field-value pairs (dictionary)
List - Ordered sequences
Set - Unordered unique collections
Sorted Set - Score-ordered unique collections
Key Operations
KEYS pattern # Pattern matching (KEYS *, KEYS a*, etc.)
TYPE key # Value type
EXPIRE key seconds # Set TTL
PEXPIRE key ms # Set TTL in milliseconds
TTL key # Remaining time in seconds
PTTL key # Remaining time in milliseconds
PERSIST key # Remove TTL
DEL key # Delete key
EXISTS key # Check existence
RENAME old new # Rename key
Examples:
127.0.0.1:6379> set username alice
127.0.0.1:6379> EXPIRE username 60
(integer) 1
127.0.0.1:6379> ttl username
(integer) 57
127.0.0.1:6379> set temp value EX 60
OK
127.0.0.1:6379> ttl temp
(integer) 60
127.0.0.1:6379> PERSIST temp
(integer) 1
127.0.0.1:6379> ttl temp
(integer) -1
String Operations
Use cases: Session storage, counters, caching.
# Basic operations
SET key value
MSET id 101 name bob age 25 gender m
# Counter operations
INCR counter # Increment by 1
INCRBY counter 10000 # Increment by specified value
DECRBY counter 5000 # Decrement by specified value
# Extended operations
SETEX key 10 value # Set with expiration (seconds)
SETNX key value # Set if not exists
GETSET key newval # Get old value and set new value
APPEND key suffix # Append to existing value
STRLEN key # String length
SETRANGE key 5 newval # Replace bytes starting at offset
GETRANGE key 0 10 # Substring extraction
Counter example:
127.0.0.1:6379> incr follower_count
(integer) 1
127.0.0.1:6379> get follower_count
1
127.0.0.1:6379> incrby follower_count 10000
(integer) 10006
127.0.0.1:6379> get follower_count
10006
Hash Operations
Use cases: User profiles, object caching, near-database performance.
# Storage
HMSET user:id:101 id 101 name alice age 25 gender f
HMSET user:id:102 id 102 name bob age 30 gender m
# Retrieval
HMGET user:id:101 id name age gender
HMGET user:id:102 id name age gender
Extended hash commands:
HSET hash field value # Set single field
HSETNX hash field value # Set if field doesn't exist
HGET hash field # Get single field
HMGET hash f1 f2 f3 # Get multiple fields
HGETALL hash # All fields and values
HLEN hash # Field count
HEXISTS hash field # Field existence check
HKEYS hash # All field names
HVALS hash # All values
HINCRBY hash field delta # Increment numeric value
HDEL hash field # Delete field
DEL hash # Delete entire hash
Bulk data import example:
SELECT CONCAT('HMSET user_', id, ' id ', id, ' name ', name)
FROM users INTO OUTFILE '/tmp/hash_import.txt'
List Operations
Use cases: Message queues, activity feeds, recent items.
# Add elements
LPUSH queue item1 item2 # Push to head
RPUSH queue item3 item4 # Push to tail
LPUSHX queue item # Push if list exists
RPUSHX queue item # Push to tail if list exists
LINSERT queue BEFORE pivot newval
LINSERT queue AFTER pivot newval
# Remove elements
LPOP queue # Pop from head
RPOP queue # Pop from tail
LREM queue count value # Remove count occurrences
LTRIM queue 0 9 # Keep specified range
# Query elements
LRANGE queue 0 -1 # All elements
LINDEX queue position # Element at index
LLEN queue # List length
WeChat timeline example:
127.0.0.1:6379> LPUSH timeline "weekend vibes!"
127.0.0.1:6379> LPUSH timeline "work hard"
127.0.0.1:6379> LPUSH timeline "coffee time"
127.0.0.1:6379> LPUSH timeline "Monday blues"
127.0.0.1:6379> LPUSH timeline "TGIF!"
127.0.0.1:6379> LRANGE timeline 0 0
1) "TGIF!"
127.0.0.1:6379> LRANGE timeline 0 2
1) "TGIF!"
2) "Monday blues"
3) "coffee time"
127.0.0.1:6379> LRANGE timeline -2 -1
1) "work hard"
2) "weekend vibes!"
Set Operations
Use cases: Social connections, tags, unique tracking.
# Add/remove members
SADD myset member1 member2 member3
SREM myset member1
SPOP myset # Remove and return random member
# Query operations
SMEMBERS myset # All members
SISMEMBER myset member # Existence check
SCARD myset # Member count
SRANDMEMBER myset [count] # Random members without removal
# Set operations
SDIFF set1 set2 # Difference
SDIFFSTORE result set1 set2
SINTER set1 set2 # Intersection
SINTERSTORE result set1 set2
SUNION set1 set2 # Union
SUNIONSTORE result set1 set2
Social graph example:
127.0.0.1:6379> SADD following alice bob charlie david eve
(integer) 5
127.0.0.1:6379> SADD followers bob alice mike frank tony
(integer) 5
127.0.0.1:6379> SUNION following followers
1) "alice"
2) "bob"
3) "charlie"
4) "david"
5) "eve"
6) "mike"
7) "frank"
8) "tony"
127.0.0.1:6379> SINTER following followers
1) "alice"
2) "bob"
127.0.0.1:6379> SDIFF followers following
1) "tony"
2) "frank"
3) "mike"
Sorted Set Operations
Use cases: Leaderboards, ranking systems, priority queues.
# Add/update members
ZADD leaderboard score member
ZINCRBY leaderboard delta member
# Remove members
ZREM leaderboard member1 member2
# Query operations
ZRANGE leaderboard 0 -1 WITHSCORES # Low to high
ZREVRANGE leaderboard 0 -1 WITHSCORES # High to low
ZRANK leaderboard member # Position (low to high)
ZREVRANK leaderboard member # Position (high to low)
ZSCORE leaderboard member # Get score
ZCARD leaderboard # Member count
ZCOUNT leaderboard min max # Score range count
ZRANGEBYSCORE leaderboard 100 500 # Score range query
ZRANGEBYSCORE leaderboard -inf +inf LIMIT 0 10
ZREMRANGEBYSCORE leaderboard 0 100 # Remove by score
ZREMRANGEBYRANK leaderboard 0 2 # Remove by rank
Leaderboard example:
127.0.0.1:6379> ZADD rankings 0 player1 0 player2 0 player3 0 player4 0 player5 0 player6
(integer) 6
127.0.0.1:6379> ZINCRBY rankings 85000 player1
85000
127.0.0.1:6379> ZINCRBY rankings 92000 player2
92000
127.0.0.1:6379> ZINCRBY rankings 120000 player3
120000
127.0.0.1:6379> ZINCRBY rankings 1000 player4
1000
127.0.0.1:6379> ZREVRANGE rankings 0 2 WITHSCORES
1) "player3"
2) "120000"
3) "player2"
4) "92000"
5) "player1"
6) "85000"
Publish/Subscribe
PUBLISH channel message
SUBSCRIBE channel [channel ...]
UNSUBSCRIBE [channel ...]
PSUBSCRIBE pattern [pattern ...]
PUNSUBSCRIBE [pattern ...]
PUBSUB subcommand [argument ...]
Note: Subscribers receive only messages published after subscription. Offline messages are not buffered.
Basic example:
# Terminal 1 - Subscriber
SUBSCRIBE news
# Terminal 2 - Publisher
PUBLISH news "Breaking: Redis 7.0 released!"
Pattern subscription:
# Subscriber
PSUBSCRIBE news.*
# Publisher
PUBLISH news.tech "Tech updates"
PUBLISH news.sports "Sports news"
Transactions
Redis transactions use optimistic locking with WATCH/MULTI/EXEC.
MULTI
SET key1 value1
SET key2 value2
INCR counter
EXEC
# Or DISCARD to cancel
Execution behavior: Commands are queued and executed atomically. All succeed or all fail.
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> SET a 100
QUEUED
127.0.0.1:6379> SET b 200
QUEUED
127.0.0.1:6379> EXEC
1) OK
2) OK
Optimistic locking (ticket reservation):
# Initial ticket
SET ticket_count 1
# Terminal 1
WATCH ticket_count
MULTI
SET ticket_count 0
# Terminal 2
MULTI
SET ticket_count 0
EXEC
# Terminal 1
EXEC
Server Management Commands
INFO # Server statistics
CLIENT LIST # Connected clients
CLIENT KILL ip:port # Disconnect client
CONFIG GET * # All configurations
CONFIG RESETSTAT # Reset statistics
CONFIG SET param value # Change config at runtime
DBSIZE # Key count
FLUSHALL # Clear all databases
FLUSHDB # Clear current database
SELECT db_num # Switch database
MONITOR # Real-time command monitoring
SHUTDOWN # Graceful shutdown
# Shutdown example
redis-cli -a password shutdown
Master-Replica Configuration
Replication Flow
- Replica connects to master and sends SYNC
- Master executes BGSAVE and sends RDB snapshot
- Replica loads RDB snapshot
- Master streams new operations to replica
- Ongoing: master pushes all writes to replicas
- Reconnection: replica sends PSYNC for incremental sync
- Only missing data is transferred on reconnect
Consistency Safeguards
min-slaves-to-write 1
min-slaves-max-lag 3
Persistence Requirement
Critical: Master must have persistence enabled. Without it, master restart causes complete data loss across all replicas.
Setup Procedure
# Create directories
mkdir /data/638{0..2}
# Master configuration (6380)
cat > /data/6380/redis.conf <<EOF
port 6380
daemonize yes
pidfile /data/6380/redis.pid
loglevel notice
logfile /data/6380/redis.log
dbfilename dump.rdb
dir /data/6380
requirepass masterpass
masterauth masterpass
EOF
# Replica configuration (6381)
cat > /data/6381/redis.conf <<EOF
port 6381
daemonize yes
pidfile /data/6381/redis.pid
loglevel notice
logfile /data/6381/redis.log
dbfilename dump.rdb
dir /data/6381
requirepass replicapass
masterauth masterpass
EOF
# Replica configuration (6382)
cat > /data/6382/redis.conf <<EOF
port 6382
daemonize yes
pidfile /data/6382/redis.pid
loglevel notice
logfile /data/6382/redis.log
dbfilename dump.rdb
dir /data/6382
requirepass replicapass
masterauth masterpass
EOF
# Start instances
redis-server /data/6380/redis.conf
redis-server /data/6381/redis.conf
redis-server /data/6382/redis.conf
# Configure replication
redis-cli -p 6381 -a replicapass SLAVEOF 127.0.0.1 6380
redis-cli -p 6382 -a replicapass SLAVEOF 127.0.0.1 6380
# Verify status
redis-cli -p 6380 -a masterpass INFO replication
redis-cli -p 6381 -a replicapass INFO replication
redis-cli -p 6382 -a replicapass INFO replication
Redis Sentinel
Sentinel provides automatic failover with these capabilities:
- Continuous monitoring
- Automatic master election
- Automatic replica reassignment
- Transparent client redirection
- Automatic node failure handling
Sentinel Setup
mkdir /data/26380
cat > /data/26380/sentinel.conf <<EOF
port 26380
dir "/data/26380"
sentinel monitor mymaster 127.0.0.1 6380 1
sentinel down-after-milliseconds mymaster 5000
sentinel auth-pass mymaster masterpass
EOF
# Launch sentinel
redis-sentinel /data/26380/sentinel.conf &
Troubleshooting
- Recreate 1-master-2-replica environment
- Terminate sentinel processes
- Clear sentinel directory
- Reinitialize sentinel
Sentinel Commands
redis-cli -p 26380
PING # Returns PONG
SENTINEL masters # List monitored masters
SENTINEL slaves <master> # List replicas
SENTINEL get-master-addr-by-name <master>
SENTINEL reset <pattern>
SENTINEL failover <master> # Manual failover
Redis Cluster
Architecture
High performance through distributed slots:
- 16384 slots distributed across master nodes
- Key slot determined by
CRC16(key) % 16384 - Automatic client redirection to correct node
High availability through master-slave pairs:
- Automatic failover when master fails
- Each master has a replica for redundancy
- Typical deployment: 3 masters with 3 replicas
Slot distribution:
- Node 1: slots 0-5500
- Node 2: slots 5501-11000
- Node 3: slots 11001-16383
Installation
# Install Ruby dependencies
yum install ruby rubygems -y
# Configure Ruby gems
gem sources -l
gem sources -a http://mirrors.aliyun.com/rubygems/
gem sources --remove https://rubygems.org/
gem install redis -v 3.3.3
Node Preparation
mkdir /data/700{0..5}
# Generate configurations for ports 7000-7005
for port in 7000 7001 7002 7003 7004 7005; do
cat > /data/${port}/redis.conf <<EOF
port ${port}
daemonize yes
pidfile /data/${port}/redis.pid
loglevel notice
logfile /data/${port}/redis.log
dbfilename dump.rdb
dir /data/${port}
protected-mode no
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes
EOF
done
# Start all nodes
for port in 7000 7001 7002 7003 7004 7005; do
redis-server /data/${port}/redis.conf
done
# Verify processes
ps -ef | grep redis-server
Cluster Creation
redis-trib.rb create --replicas 1 \
127.0.0.1:7000 127.0.0.1:7001 \
127.0.0.1:7002 127.0.0.1:7003 \
127.0.0.1:7004 127.0.0.1:7005
Cluster Management
Add new master:
# Create new directories and configs
mkdir /data/7006 /data/7007
# Start new nodes
redis-server /data/7006/redis.conf
redis-server /data/7007/redis.conf
# Add master to cluster
redis-trib.rb add-node 127.0.0.1:7006 127.0.0.1:7000
# Reshard slots to new master
redis-trib.rb reshard 127.0.0.1:7000
Add replica:
redis-trib.rb add-node --slave \
--master-id <master-node-id> \
127.0.0.1:7007 127.0.0.1:7000
Remove node:
# Reshard all slots away from target node first
redis-trib.rb reshard 127.0.0.1:7000
# Delete the node
redis-trib.rb del-node 127.0.0.1:7006 <node-id>
Memory management:
CONFIG SET maxmemory 102400000
Python Client Integration
Installation
yum install -y python36 python36-pip
pip3 install redis
pip3 install redis-py-cluster
Single Instance Connection
import redis
r = redis.StrictRedis(host='10.0.0.51', port=6379, db=0, password='mypassword')
r.set('username', 'alice')
print(r.get('username'))
Sentinel Connection
from redis.sentinel import Sentinel
sentinel = Sentinel([('localhost', 26380)], socket_timeout=0.1)
# Discover master and slaves
master_info = sentinel.discover_master('mymaster')
slave_info = sentinel.discover_slaves('mymaster')
# Create connection pools
master = sentinel.master_for('mymaster', socket_timeout=0.1, password='mypassword')
slave = sentinel.slave_for('mymaster', socket_timeout=0.1, password='mypassword')
# Read-write splitting
master.set('session:123', 'data_value')
result = slave.get('session:123')
Cluster Connection
from rediscluster import StrictRedisCluster
startup_nodes = [
{"host": "127.0.0.1", "port": "7000"},
{"host": "127.0.0.1", "port": "7001"},
{"host": "127.0.0.1", "port": "7002"}
]
rc = StrictRedisCluster(startup_nodes=startup_nodes, decode_responses=True)
rc.set("cache_key", "cache_value")
print(rc.get("cache_key"))
Cache Design Patterns
Cache Penetration
Problem: Requests for non-existent keys bypass cache and hit database directly.
Soluitons:
- Bloom filter: Maintain a bitmap of possible keys; reject non-existent keys early
- Null caching: Store null values with short TTL for missing keys
Cache Avalanche
Problem: Mass keys expire simultaneously, causing database overload.
Solutions:
- Add random jitter to TTL values:
actual_ttl = base_ttl + random(0, 300) - Stagger expiration times across key groups
Cache Breakdown
Problem: A single hot key expires; concurrent requests all hit database.
Solutions:
- Use distributed locking:
SETNX lock:key value EX 10 - Only the lock holder queries database; others wait and read from cache
- Release lock after cache population