Truy vấn database mất 200ms và lặp lại hàng nghìn lần mỗi phút với cùng một kết quả. Redis lưu kết quả đó trong RAM và trả về trong chưa tới 1ms.
Kết nối
pip install redis
import redis
r = redis.Redis(host="localhost", port=6379, db=0, decode_responses=True)
r.set("ten", "An")
print(r.get("ten")) # An
decode_responses=True giúp bạn nhận chuỗi thay vì bytes — bỏ qua tùy chọn này là phiền toái phổ biến nhất của người mới.
TTL: linh hồn của cache
r.setex("phien:abc123", 3600, "user_id=42") # tự xóa sau 1 giờ
print(r.ttl("phien:abc123")) # số giây còn lại
Gần như mọi khóa cache đều nên có TTL. Không có nó, Redis sẽ đầy dần và dữ liệu cũ tồn tại mãi.
Mẫu cache-aside
import json
def lay_san_pham(ma):
khoa = f"sanpham:{ma}"
cache = r.get(khoa)
if cache:
return json.loads(cache) # trúng cache
du_lieu = truy_van_database(ma) # trượt cache
r.setex(khoa, 300, json.dumps(du_lieu))
return du_lieu
Các kiểu dữ liệu hữu ích
# Đếm — an toàn khi nhiều tiến trình cùng tăng
r.incr("luot_xem:bai-viet-10")
# Hash — lưu đối tượng theo trường
r.hset("nguoidung:42", mapping={"ten": "An", "email": "[email protected]"})
r.hget("nguoidung:42", "ten")
# Set — danh sách không trùng
r.sadd("da_xem:42", "bai-1", "bai-2")
r.sismember("da_xem:42", "bai-1") # True
# List — hàng đợi đơn giản
r.lpush("hang_doi", "viec-1")
r.rpop("hang_doi")
Giới hạn tốc độ trong vài dòng
def cho_phep(ip, gioi_han=100, cua_so=60):
khoa = f"rate:{ip}"
so_lan = r.incr(khoa)
if so_lan == 1:
r.expire(khoa, cua_so)
return so_lan <= gioi_han
Xóa cache khi dữ liệu đổi
def cap_nhat_san_pham(ma, du_lieu):
luu_vao_database(ma, du_lieu)
r.delete(f"sanpham:{ma}") # buộc lần đọc sau lấy dữ liệu mới
Nhớ rằng Redis nằm trong RAM
Đừng coi nó là nơi lưu trữ chính. Ứng dụng phải chạy đúng — chỉ chậm hơn — khi Redis mất toàn bộ dữ liệu. Hãy đặt maxmemory và chính sách allkeys-lru để Redis tự loại bỏ khóa cũ khi đầy.
