Vấn đề đầu tiên phải nêu: UPDATE posts SET views = views + 1 mỗi lượt xem sẽ khoá cùng một dòng — bài viral biến thành điểm nóng và làm chậm cả bảng.
Cách làm: đếm ở Redis, ghi xuống DB theo lô.
INCR post:{id}:views:2026-08-06 -- bo dem theo ngay
ZINCRBY trending:2026-08-06 1 {postId} -- bang xep hang
EXPIRE trending:2026-08-06 172800INCRlà thao tác nguyên tử, chi phí rất thấp.- Sorted set cho bảng xếp hạng: lấy top 20 chỉ là
ZREVRANGE trending:{day} 0 19, độ phức tạp log, không cầnORDER BY ... LIMITtrên bảng lớn. - Job mỗi phút đọc bộ đếm ghi vào Postgres để có số liệu bền vững và phục vụ báo cáo.
Chống đếm gian: một người F5 mười lần không nên tính mười view. Khử trùng lặp theo cửa sổ thời gian bằng key seen:{postId}:{userOrIpHash} với TTL 30 phút, hoặc dùng HyperLogLog khi chỉ cần số lượt xem duy nhất ước lượng (sai số ~0.8%, tốn vài KB thay vì lưu toàn bộ id).
Điểm nghẽn:
- Redis mất dữ liệu khi restart → chấp nhận sai lệch nhỏ ở bộ đếm view (không phải dữ liệu tiền), hoặc bật AOF nếu cần chắc hơn.
- Bảng xếp hạng theo ngày cần TTL, nếu không key sẽ tích tụ vô hạn.
Đánh đổi: số hiển thị trễ và gần đúng thay vì chính xác tuyệt đối. Với lượt xem thì đúng-gần-đúng là đủ, và đổi lại hệ thống chịu được tải cao gấp nhiều lần. Nếu phỏng vấn hỏi "vậy số liệu quảng cáo tính tiền thì sao" — lúc đó phải dùng đường ghi bền vững có đối soát, không dùng bộ đếm trong bộ nhớ.