Làm rõ yêu cầu trước: ai tạo link (nội bộ marketing, không phải public), link có hạn dùng không, thống kê cần real-time hay trễ vài phút. Giả sử 100k link, 5 triệu click/tháng — tức chỉ ~2 click/giây trung bình, đỉnh chiến dịch có thể 500/giây. Quy mô này một Postgres + Redis là đủ, đừng vẽ sharding.
API và data model:
POST /links { targetUrl, campaign, expiresAt } -> { code }
GET /{code} -> 302 Location: targetUrl
GET /links/{code}/statslinks(code pk, target_url, campaign_id, created_by, expires_at)
click_events(id, code, ts, referer, ua_hash, country)
click_daily(code, day, count) -- bảng tổng hợpSinh code: dùng counter tăng dần (sequence của DB) rồi mã hoá base62 — ngắn, không đụng nhau, không cần vòng lặp retry như random. Nếu sợ đoán được link kế tiếp thì trộn counter qua một phép hoán vị cố định.
Kiến trúc: redirect là đường nóng — nạp code -> target_url vào Redis, miss mới xuống DB. Ghi click không chặn redirect: trả 302 ngay, đẩy event vào queue, worker gộp vào click_daily.
Điểm nghẽn và đánh đổi:
- Bảng click_events lớn nhanh nhất → giữ raw 30 ngày, phần còn lại chỉ giữ bảng tổng hợp.
- Thống kê "real-time" đắt: nếu chấp nhận trễ 1 phút thì tăng ngưỡng gộp, tải DB giảm hẳn.
- Link đã tạo nên bất biến (không cho sửa target) — sửa được thì link đã phát ra ngoài trở thành lỗ hổng chuyển hướng.