Họ đang đo gì
Bạn có phân biệt được “tránh làm việc thừa” với “không được phép xảy ra hai lần” không.
Trả lời ngắn~30 giây
Nếu khoá chỉ để tránh hai instance cùng làm một việc tốn kém, thì SET key value NX PX 30000 là đủ và rất phổ biến. Nếu việc chạy hai lần gây SAI dữ liệu, thì khoá phân tán không đủ — vì instance giữ khoá có thể bị GC pause hoặc mất mạng, khoá hết hạn, instance khác lấy khoá, rồi instance đầu tỉnh dậy và vẫn tưởng mình đang giữ. Không có timeout nào loại bỏ được kịch bản này.
Giải thích sâu
Cách xử lý đúng cho trường hợp tính đúng đắn là fencing token: mỗi lần cấp khoá, dịch vụ khoá trả về một số tăng dần, và TÀI NGUYÊN được bảo vệ từ chối mọi ghi có token nhỏ hơn token lớn nhất nó từng thấy. Nghĩa là instance ngủ dậy muộn vẫn ghi được nhưng sẽ bị từ chối. Điểm mấu chốt là việc kiểm tra nằm ở phía tài nguyên, không ở phía client — nếu tài nguyên không hỗ trợ điều đó thì bạn không có bảo đảm nào cả.
Về Redlock, thuật toán dùng nhiều node Redis: nó gây tranh cãi công khai giữa Martin Kleppmann và Salvatore Sanfilippo, và điểm quan trọng rút ra là nó dựa vào giả định về đồng hồ và về độ trễ mạng có giới hạn — hai thứ không đúng trong hệ bất đồng bộ. Với tính đúng đắn thật sự thì thứ bạn cần là một hệ đồng thuận (etcd, ZooKeeper, Consul) chứ không phải một cache.
Nhưng câu trả lời thực dụng nhất thường là tránh cần khoá. Nếu job có thể chạy hai lần mà kết quả không đổi — nghĩa là idempotent — thì bạn không cần bảo đảm gì. Nếu công việc có thể chia theo khoá và mỗi khoá do một partition xử lý, bạn cũng không cần. Rất nhiều nhu cầu khoá phân tán biến mất khi thiết kế lại theo hướng đó, và đề xuất được điều này là tín hiệu senior rõ hơn cả việc kể tên etcd.
Câu hỏi tiếp theo họ sẽ hỏi
?Chạy cron trên nhiều instance thì sao?
Đừng để mỗi instance tự chạy cron. Dùng một bộ lập lịch bên ngoài (Kubernetes CronJob, hoặc hàng đợi có lịch) tạo đúng một job, rồi instance nào rảnh thì nhận. Nó chuyển bài toán từ “loại trừ lẫn nhau” sang “phân phối công việc”, vốn dễ hơn nhiều.
Trả lời thế này là mất điểm
SETNXrồiEXPIREthành hai lệnh. Chết giữa hai lệnh là khoá tồn tại vĩnh viễn. Phải dùngSET … NX PXmột lệnh.- Xoá khoá mà không kiểm tra chủ sở hữu. Bạn có thể xoá khoá của người khác sau khi khoá của mình đã hết hạn — cần script Lua so sánh giá trị rồi mới xoá.