Họ đang đo gì
Bạn có làm rõ yêu cầu và ước lượng con số trước khi vẽ hộp không.
Trả lời ngắn~30 giây
Mình bắt đầu bằng con số: giả sử 100 triệu link mới mỗi tháng và tỷ lệ đọc/ghi 100:1, tức khoảng 40 lượt ghi/giây và 4.000 lượt đọc/giây. Đó là hệ thống đọc là chính, nên cache đứng trước database sẽ gánh phần lớn. Khoá dùng base62 7 ký tự cho 3,5 nghìn tỷ tổ hợp; sinh bằng bộ đếm phân tán mã hoá base62 thay vì hash, vì hash cần xử lý va chạm còn bộ đếm thì không. Lưu trong một kho khoá–giá trị, redirect bằng 301 hoặc 302 tuỳ có cần thống kê hay không.
Giải thích sâu
Lựa chọn 301 hay 302 là chi tiết nhỏ mà người phỏng vấn rất thích, vì nó cho thấy bạn nghĩ tới hậu quả. 301 là chuyển hướng vĩnh viễn nên trình duyệt cache lại và các lần bấm sau không chạm tới server bạn — nhanh và rẻ, nhưng bạn mất thống kê và không thể đổi đích. 302 thì mọi lần bấm đều đi qua bạn — đếm được, đổi được, và tốn hơn. Nếu sản phẩm bán tính năng phân tích thì lựa chọn đã rõ.
Về sinh khoá, cách dùng bộ đếm gặp một vấn đề: khoá tuần tự thì đoán được, nên ai cũng liệt kê được toàn bộ link của bạn. Cách xử lý phổ biến là mỗi node lấy trước một DẢI số (ví dụ 1.000 số một lần) từ một dịch vụ cấp phát, rồi trộn bit trong dải đó — vẫn không va chạm, nhưng không còn liên tiếp. Nếu cần bí mật thật thì phải dùng khoá ngẫu nhiên và chấp nhận kiểm tra va chạm.
Phần thường bị bỏ qua nhất là link nóng. Phân phối lượt bấm cực kỳ lệch: một link viral chiếm phần lớn lưu lượng trong vài giờ. Nghĩa là cache theo LRU đủ tốt, nhưng bạn phải nghĩ tới hot key trong cache phân tán — một khoá duy nhất dồn hết vào một shard Redis. Cách xử lý là sao chép khoá nóng ra nhiều shard hoặc thêm một tầng cache trong bộ nhớ ứng dụng với TTL rất ngắn.
Câu hỏi tiếp theo họ sẽ hỏi
?Link tuỳ chỉnh (custom alias) thì sao?
Nó biến bài toán thành có tranh chấp: hai người cùng xin /sale một lúc. Cần ràng buộc UNIQUE ở tầng lưu trữ và trả 409 cho người thua — không thể chỉ kiểm tra trước rồi ghi, vì đó là race condition.
?Link hết hạn thì dọn thế nào?
Đừng chạy job quét bảng. Lưu expires_at và kiểm tra lúc đọc — link hết hạn trả 410 — rồi dọn nền theo phân vùng thời gian. Với Redis thì TTL làm sẵn việc này.
Trả lời thế này là mất điểm
- Vẽ kiến trúc trước khi hỏi quy mô. 1.000 link một ngày và 1 tỷ link một ngày là hai hệ thống khác hẳn nhau.
- Dùng MD5 cắt ngắn làm khoá mà không nói tới va chạm. Cắt ngắn hash thì va chạm đến sớm hơn nhiều so với trực giác.