Redis - Lý Thuyết Cơ Bản

📚 Giới Thiệu

Redis (Remote Dictionary Server) là in-memory data structure store, được sử dụng như database, cache, message broker và streaming engine. Nổi tiếng với performance cao và data structures phong phú.

🏗️ Kiến Trúc Redis

1. Memory Architecture

Client Applications
       ↓
Redis Server (Single-threaded main loop)
       ↓
Memory (RAM) ← Primary storage
       ↓
Persistence (RDB/AOF) ← Optional disk storage

2. Single-threaded Model

  • Main thread: Xử lý tất cả commands
  • Background threads: Persistence, cleanup tasks
  • Event-driven: Non-blocking I/O với event loop
  • Atomic operations: Tất cả operations là atomic

3. Networking Model

Multiple Clients → Redis Server (6379) → Single Event Loop
                                     ↓
                              Command Processing Queue
                                     ↓
                              Response to Clients

📊 Data Structures

1. Strings

# Basic string operations
SET mykey "Hello World"
GET mykey
INCR counter
INCRBY counter 5
APPEND mykey " Redis"

# String with expiration
SETEX session:user123 3600 "user_data"

# Atomic increment
INCR page_views

Use Cases: - Caching web pages, API responses - Session storage - Counters và metrics - Feature flags

2. Hashes

# Hash operations
HSET user:1000 name "John Doe" email "john@example.com" age 30
HGET user:1000 name
HGETALL user:1000
HINCRBY user:1000 age 1

# Multiple field operations
HMSET user:1001 name "Alice" email "alice@example.com" status "active"
HMGET user:1001 name email

Use Cases: - User profiles - Configuration settings - Object representation - Shopping carts

3. Lists

# List operations (LIFO/FIFO)
LPUSH tasks "task1" "task2" "task3"
RPUSH queue "item1" "item2"
LPOP tasks
RPOP queue
LRANGE tasks 0 -1

# Blocking operations
BLPOP queue 10  # Block for 10 seconds if empty
BRPOPLPUSH source destination 5

Use Cases: - Message queues - Activity feeds - Recent items lists - Task queues

4. Sets

# Set operations
SADD myset "apple" "banana" "orange"
SMEMBERS myset
SISMEMBER myset "apple"
SCARD myset

# Set operations
SADD set1 "a" "b" "c"
SADD set2 "b" "c" "d"
SINTER set1 set2      # Intersection
SUNION set1 set2      # Union
SDIFF set1 set2       # Difference

Use Cases: - Tags/categories - Unique visitors tracking - Social network connections - Permissions/roles

5. Sorted Sets (ZSets)

# Sorted set operations
ZADD leaderboard 100 "player1" 85 "player2" 92 "player3"
ZRANGE leaderboard 0 -1 WITHSCORES
ZREVRANGE leaderboard 0 2  # Top 3 players
ZINCRBY leaderboard 5 "player2"

# Range queries
ZRANGEBYSCORE leaderboard 80 95
ZCOUNT leaderboard 80 100

Use Cases: - Leaderboards - Priority queues - Time-series data - Rate limiting

6. Streams

# Stream operations
XADD mystream * name "John" action "login" timestamp 1642678800
XREAD STREAMS mystream 0

# Consumer groups
XGROUP CREATE mystream mygroup $ MKSTREAM
XREADGROUP GROUP mygroup consumer1 STREAMS mystream >

Use Cases: - Event sourcing - Activity logs - Real-time analytics - Message streaming

🔍 Advanced Features

1. Pub/Sub Messaging

# Publisher
PUBLISH news "Breaking news: Redis 7.0 released!"

# Subscriber
SUBSCRIBE news sports
PSUBSCRIBE news:*  # Pattern subscription

# Channels management
PUBSUB CHANNELS
PUBSUB NUMSUB news

Use Cases: - Real-time notifications - Chat applications - Live updates - Event broadcasting

2. Transactions

# Multi/Exec transaction
MULTI
SET key1 "value1"
INCR counter
SET key2 "value2"
EXEC

# Watch for changes
WATCH mykey
MULTI
SET mykey "new_value"
EXEC  # Fails if mykey changed after WATCH

Features: - Atomic: All or nothing execution - Isolated: Commands queued until EXEC - Optimistic locking: WATCH command - No rollback: Failed commands don't rollback others

3. Lua Scripting

-- Atomic increment with maximum
local current = redis.call('GET', KEYS[1])
if current == false then
    current = 0
else
    current = tonumber(current)
end

if current < tonumber(ARGV[1]) then
    return redis.call('INCR', KEYS[1])
else
    return current
end
# Execute Lua script
EVAL "return redis.call('SET', KEYS[1], ARGV[1])" 1 mykey myvalue

4. Modules

# RedisJSON
JSON.SET user:1 $ '{"name":"John","age":30}'
JSON.GET user:1 $.name

# RedisTimeSeries
TS.CREATE temperature
TS.ADD temperature 1642678800000 25.5

# RediSearch
FT.CREATE idx SCHEMA title TEXT WEIGHT 5.0 body TEXT
FT.SEARCH idx "hello world"

💾 Persistence

1. RDB (Redis Database)

# Manual snapshot
SAVE       # Blocking save
BGSAVE     # Non-blocking background save

# Configuration
save 900 1    # Save if at least 1 key changed in 900 seconds
save 300 10   # Save if at least 10 keys changed in 300 seconds
save 60 10000 # Save if at least 10000 keys changed in 60 seconds

Characteristics: - Point-in-time snapshots - Compact file format - Faster restarts - Data loss possible (last snapshot)

2. AOF (Append Only File)

# AOF configuration
appendonly yes
appendfsync everysec  # always, everysec, no

# AOF rewrite
BGREWRITEAOF

# Example AOF content:
*2
$6
SELECT
$1
0
*3
$3
SET
$3
key
$5
value

Characteristics: - Log of write operations - Better durability - Larger files - Automatic rewrite for compaction

3. Hybrid Persistence

# Redis 4.0+ hybrid persistence
aof-use-rdb-preamble yes

# Creates RDB format in AOF file for faster loading
# AOF commands appended after RDB data

🔄 Replication

1. Master-Slave Setup

# On slave
REPLICAOF 192.168.1.100 6379

# Configuration
# redis.conf on slave:
# replicaof 192.168.1.100 6379
# replica-read-only yes

2. Replication Process

Master → Binary logs → Slave
      ↓
   RDB snapshot (initial sync)
      ↓
   Incremental commands

3. Sentinel for HA

# sentinel.conf
port 26379
sentinel monitor mymaster 192.168.1.100 6379 2
sentinel down-after-milliseconds mymaster 5000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 60000

Sentinel Features: - Monitoring: Check master và replica health - Notification: Alert about issues - Automatic failover: Promote replica to master - Configuration provider: Service discovery

🔀 Clustering

1. Redis Cluster Architecture

Cluster với 6 nodes (3 masters, 3 slaves):
Master A (0-5460)     → Slave A'
Master B (5461-10922) → Slave B' 
Master C (10923-16383) → Slave C'

2. Cluster Setup

# Enable cluster mode
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000

# Create cluster
redis-cli --cluster create \
  192.168.1.100:6379 192.168.1.101:6379 192.168.1.102:6379 \
  192.168.1.103:6379 192.168.1.104:6379 192.168.1.105:6379 \
  --cluster-replicas 1

3. Hash Slots

# 16384 hash slots (0-16383)
# CRC16(key) % 16384 determines slot

# Hash tags for related keys
SET {user:1000}:profile "data"
SET {user:1000}:preferences "settings"
# Both keys go to same slot/node

⚡ Performance Optimization

1. Memory Optimization

# Memory usage analysis
MEMORY USAGE key
MEMORY STATS
INFO memory

# Configuration for memory efficiency
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
set-max-intset-entries 512
zset-max-ziplist-entries 128

2. Connection Pooling

import redis.connection

# Connection pool
pool = redis.ConnectionPool(
    host='localhost',
    port=6379,
    max_connections=20,
    socket_keepalive=True,
    socket_keepalive_options={}
)

redis_client = redis.Redis(connection_pool=pool)

3. Pipeline Operations

# Batch operations for better performance
pipe = redis_client.pipeline()
pipe.set('key1', 'value1')
pipe.set('key2', 'value2')
pipe.incr('counter')
pipe.execute()  # Send all commands at once

4. Memory Policies

# Eviction policies
maxmemory 1gb
maxmemory-policy allkeys-lru

# Available policies:
# noeviction - return errors when memory limit reached
# allkeys-lru - evict least recently used keys
# volatile-lru - evict LRU among keys with expire set
# allkeys-random - randomly evict keys
# volatile-random - randomly evict among keys with expire
# volatile-ttl - evict keys with shortest TTL first

🔒 Security

1. Authentication

# Set password
requirepass mypassword

# Client authentication
AUTH mypassword

# Multiple users (Redis 6.0+)
ACL SETUSER alice on >password1 ~* +@all
ACL SETUSER bob on >password2 ~cache:* +get +set

2. Network Security

# Bind to specific interfaces
bind 127.0.0.1 192.168.1.100

# Protected mode
protected-mode yes

# Disable dangerous commands
rename-command FLUSHDB ""
rename-command FLUSHALL ""
rename-command CONFIG "CONFIG_abc123"

3. SSL/TLS

# Redis 6.0+ TLS support
port 0
tls-port 6380
tls-cert-file /path/to/redis.crt
tls-key-file /path/to/redis.key
tls-ca-cert-file /path/to/ca.crt

📊 Monitoring & Debugging

1. INFO Command

# Server information
INFO server
INFO memory
INFO replication
INFO persistence
INFO stats
INFO clients

2. Slow Log

# Configure slow log
slowlog-log-slower-than 10000  # 10ms
slowlog-max-len 128

# View slow queries
SLOWLOG GET 10
SLOWLOG RESET

3. CLIENT Commands

# Monitor clients
CLIENT LIST
CLIENT INFO
CLIENT KILL ip:port

# Monitor commands
MONITOR  # Real-time command monitoring

4. Key Analysis

# Analyze keyspace
DBSIZE
SCAN 0 MATCH "user:*" COUNT 1000

# Key patterns and memory usage
redis-cli --bigkeys
redis-cli --memkeys

🛠️ Best Practices

1. Key Naming Conventions

# Use consistent naming patterns
user:1000:profile
user:1000:settings
session:abc123
cache:user:1000:posts

# Avoid very long key names
# Good: u:1000:p
# Bad: user:1000:profile:detailed:information

2. Data Structure Selection

# Choose appropriate data structure
# Strings: Simple values, counters
# Hashes: Objects with fields
# Lists: Queues, stacks
# Sets: Unique items, tags
# Sorted Sets: Rankings, time series

3. Expiration Strategies

# Set appropriate TTL
SETEX cache:key 3600 "value"  # 1 hour
EXPIRE session:key 1800       # 30 minutes

# Lazy expiration + active expiration
# Redis automatically handles expired keys

Redis knowledge cung cấp foundation mạnh mẽ cho high-performance applications và system design.