Hướng dẫn cài đặt và sử dụng Redis cơ bản — Từ 2 giờ sáng production đến thuần thục

Database tutorial - IT technology blog
Database tutorial - IT technology blog

2 giờ sáng, server Django chậm như rùa — và Redis là thứ mình thiếu

Hồi đó mình đang chạy một API Django trả về danh sách sản phẩm cho app mobile. Mọi thứ ổn lúc traffic thấp. Nhưng đến đợt sale, server bắt đầu timeout. Mình nhảy vào check thì thấy MySQL đang chịu cỡ 400 query/giây — đa số là cùng một câu SELECT giống hệt nhau, chỉ khác nhau tham số filter.

Nguyên nhân không khó tìm: mỗi request đều đánh thẳng vào database, dù kết quả không thay đổi trong 5 phút. Cái đó gọi là missing cache layer.

Tại sao database quá tải dù query đơn giản?

Mỗi lần client gọi API /products?category=shoes, Django chạy một câu SQL đầy đủ, MySQL phải parse → tìm index → đọc từ disk (hoặc buffer pool) → trả về. Với 400 query/giây mà 80% trùng nhau, MySQL dùng gần hết CPU chỉ để làm việc lặp đi lặp lại.

Fix đơn giản nhất: thêm một layer cache ở giữa. Lần đầu query thật, kết quả lưu vào cache. Lần sau — trả từ cache, không chạm database. Đây chính xác là thứ Redis làm tốt nhất.

Cài Redis trên Linux — nhanh và sạch

Ubuntu / Debian

# Cài từ repo chính thức của Redis (mới nhất, không phải bản cũ từ Ubuntu)
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
sudo apt install redis -y

# Kiểm tra trạng thái
sudo systemctl status redis
sudo systemctl enable redis

CentOS / RHEL / Rocky Linux

sudo dnf install epel-release -y
sudo dnf install redis -y
sudo systemctl start redis
sudo systemctl enable redis

Xác nhận Redis đang chạy

redis-cli ping
# Kết quả: PONG

Thấy PONG là xong. Không thấy thì check lại systemctl status redis — 99% là service chưa start hoặc port 6379 bị firewall chặn.

Lệnh Redis hay dùng nhất trong thực tế

SET và GET — đơn giản nhất

redis-cli

# Lưu giá trị
SET username "hoanganh"

# Đọc lại
GET username
# => "hoanganh"

# Lưu có TTL (tự xóa sau 300 giây)
SET session_token "abc123" EX 300

# Xem còn bao nhiêu giây
TTL session_token

Hash — lưu object có nhiều field

# Lưu thông tin user
HSET user:1001 name "Hoàng Anh" email "[email protected]" age 28

# Đọc một field
HGET user:1001 name

# Đọc tất cả
HGETALL user:1001

List — queue đơn giản

# Thêm vào đầu
LPUSH job_queue "send_email"
LPUSH job_queue "resize_image"

# Lấy ra từ cuối (FIFO)
RPOP job_queue
# => "send_email"

Xóa và kiểm tra key

# Kiểm tra key có tồn tại không
EXISTS username
# => 1 (có) hoặc 0 (không)

# Xóa key
DEL username

# Xem tất cả key (đừng dùng trên production — nguy hiểm)
KEYS *

# Dùng SCAN thay thế trên production
SCAN 0 MATCH user:* COUNT 100

Dùng Redis cache trong Python — ví dụ thực tế

Quay lại bài toán API Django ban đầu. Đây là cách mình fix trong đêm đó:

import redis
import json
import hashlib

# Kết nối Redis
r = redis.Redis(host='localhost', port=6379, db=0, decode_responses=True)

def get_products(category: str, filters: dict) -> list:
    # Tạo cache key từ tham số query
    cache_key = f"products:{category}:{hashlib.md5(json.dumps(filters, sort_keys=True).encode()).hexdigest()}"

    # Thử lấy từ cache
    cached = r.get(cache_key)
    if cached:
        return json.loads(cached)

    # Cache miss → query database
    results = db.query("SELECT * FROM products WHERE category = %s ...", category)

    # Lưu vào cache, TTL 5 phút
    r.setex(cache_key, 300, json.dumps(results))

    return results

Deploy xong ngay trong đêm. Query MySQL giảm từ 400/giây còn khoảng 40/giây. Response time từ 800ms xuống 20ms. Chỉ 30 dòng code cache mà server không còn timeout nữa.

Cấu hình Redis tối thiểu cho production

File config mặc định ở /etc/redis/redis.conf. Mấy thứ cần chỉnh ngay:

# Giới hạn RAM Redis được dùng
maxmemory 512mb

# Khi đầy RAM: xóa key gần hết hạn trước (phù hợp cho cache)
maxmemory-policy allkeys-lru

# Bind localhost thôi, đừng expose ra ngoài nếu không cần
bind 127.0.0.1

# Đặt password (bắt buộc nếu có port mở ra ngoài)
requirepass your_strong_password_here

# Lưu snapshot ra disk (RDB persistence)
save 900 1
save 300 10
save 60 10000

Sau khi sửa config:

sudo systemctl restart redis

# Test xác thực
redis-cli -a your_strong_password_here ping

Dùng Redis đúng bài toán — đừng nhét vào chỗ không hợp

Redis mạnh thật, nhưng không phải thứ giải quyết được mọi bài toán. Mình từng thấy một team dùng Redis làm primary database cho đơn hàng — không bật persistence, restart server một cái là mất sạch dữ liệu 3 ngày giao dịch. Bài học không rẻ: hiểu đúng vai trò từng tool trước khi đụng vào production data.

Redis phù hợp nhất cho:

  • Cache API response — giảm tải database, tăng tốc độ đọc
  • Session storage — lưu session user, token xác thực
  • Rate limiting — đếm request per IP, chống spam
  • Job queue — kết hợp với Celery hoặc RQ
  • Pub/Sub messaging — real-time notification đơn giản

Không nên dùng Redis cho:

  • Dữ liệu cần bền vững tuyệt đối (đơn hàng, giao dịch tài chính)
  • Dữ liệu quan hệ phức tạp (join nhiều bảng)
  • File lớn hoặc blob nhị phân

Monitor Redis nhanh

# Xem thống kê realtime
redis-cli info stats

# Hit rate của cache
redis-cli info stats | grep -E 'keyspace_hits|keyspace_misses'

# Xem lệnh đang chạy realtime (như top nhưng cho Redis)
redis-cli monitor

keyspace_hits cao hơn keyspace_misses nhiều — cache đang hoạt động tốt. Ngược lại thì xem lại TTL và logic cache key.

Redis không khó. Mình cài lần đầu xong là dùng được ngay. Vấn đề không phải ở cài đặt — mà là biết khi nào cần và cấu hình đúng để không sập lúc không ngờ. Lần tới server ì ạch lúc đêm khuya, thử check cache layer trước — nhiều khả năng là đó.

Share: