Explore all courses in this category.
Explore all courses in this category.
Nguyễn Đình Cường
0 comment
09 Nov, 2026
Thêm Redis vào ứng dụng không tự khiến nó nhanh hơn. Cái làm nên khác biệt là chiến lược: lưu gì, lưu bao lâu, xóa khi nào và xử lý ra sao khi cache trống. Bài này tổng hợp những mẫu cache phổ biến và các cạm bẫy cần tránh.
Ứng dụng chủ động quản lý cache. Khi đọc: kiểm tra cache trước, nếu không có thì đọc database rồi ghi vào cache.
import json, redisr = redis.Redis(decode_responses=True)def get_product(product_id): key = f"product:{product_id}" cached = r.get(key) if cached: return json.loads(cached) # cache hit product = db.fetch_product(product_id) # cache miss: hỏi database if product: r.set(key, json.dumps(product), ex=300) # lưu 5 phút return productƯu điểm: đơn giản, chỉ dữ liệu thực sự được yêu cầu mới vào cache, và nếu Redis chết thì ứng dụng vẫn chạy được (chậm hơn) nhờ database.
Cache-aside là điểm khởi đầu hợp lý cho hầu hết ứng dụng.
TTL (thời gian sống) là lưới an toàn: dù bạn quên xóa, dữ liệu cũ cũng tự hết hạn. Chọn TTL theo mức chịu đựng dữ liệu cũ của nghiệp vụ: vài giây cho dữ liệu nóng thay đổi liên tục, vài phút hay vài giờ cho danh mục ít đổi. Nên cộng thêm một chút ngẫu nhiên vào TTL để nhiều khóa không cùng hết hạn một lúc:
import randomttl = 300 + random.randint(0, 60)r.set(key, value, ex=ttl)Khi dữ liệu thay đổi, xóa khóa tương ứng để lần đọc sau nạp lại bản mới:
def update_product(product_id, data): db.update_product(product_id, data) r.delete(f"product:{product_id}")Thứ tự "cập nhật database rồi xóa cache" thường an toàn hơn thứ tự ngược lại, vì tránh được tình huống một request khác nạp lại dữ liệu cũ vào cache ở giữa hai bước.
Khi một khóa nóng hết hạn, hàng trăm request cùng thấy cache trống và cùng đổ về database để tính lại, có thể làm database quá tải. Một số cách giảm thiểu:
if r.set(f"lock:{key}", "1", nx=True, ex=10): # giành được khóa value = compute_expensive() r.set(key, value, ex=300) r.delete(f"lock:{key}")Nếu ai đó liên tục hỏi id không có thật, mọi request đều xuyên qua cache tới database. Giải pháp: cache cả kết quả "không tìm thấy" với TTL ngắn, hoặc dùng bộ lọc như Bloom filter cho các hệ thống lớn.
product:v2:42).INFO stats.allkeys-lru.Một lỗi nghiêm trọng thường gặp là cache nội dung riêng của từng người dùng dưới một khóa chung, khiến người này nhìn thấy dữ liệu của người khác. Với dữ liệu cá nhân, hãy đưa định danh người dùng vào khóa, ví dụ cart:user:42, hoặc đơn giản là không cache. Tương tự, khi cache phản hồi API theo tham số, mọi tham số ảnh hưởng đến kết quả (ngôn ngữ, bộ lọc, trang) đều phải nằm trong khóa. Sai một chi tiết nhỏ ở đây có thể gây lộ dữ liệu, nên hãy xem lại kỹ khi review code.
Hãy lấy endpoint chậm nhất của bạn, thêm cache-aside với TTL ngắn, rồi đo thời gian phản hồi trước và sau. Hãy luôn kiểm tra lại bằng thực hành thay vì chỉ đọc lý thuyết: dựng một dự án nhỏ, cố tình tạo lỗi, quan sát log và công cụ gỡ lỗi, rồi sửa. Sau đó thử giả lập hết hạn đồng loạt để xem hiện tượng dồn tải và thử cách khóa tính lại.
Cache giỏi là cache có kế hoạch: mẫu cache-aside, TTL hợp lý, xóa khi dữ liệu đổi và phòng ngừa các hiện tượng dồn tải. Hãy bắt đầu từ truy vấn chậm nhất, đo trước và sau, và luôn nhớ rằng database mới là nguồn sự thật.
Nếu muốn luyện tập cùng bài tập thực tế, hãy ghé các khóa học tại codebem.com khi bạn sẵn sàng.
Nguyễn Đình Cường
0 comment