Pessimistic vs Optimistic Locking: Khi nào nên "khóa chặt", khi nào nên "thả lỏng"?
Trong thế giới của các hệ thống có tính đồng thời cao (concurrency), việc nhiều request cùng muốn chỉnh sửa một dòng dữ liệu là chuyện như cơm bữa. Nếu không có cơ chế kiểm soát, dữ liệu của bạn sẽ sớm trở thành một đống hỗn độn.
Hôm nay, hãy cùng mình đặt lên bàn cân hai chiến thần trong việc quản lý xung đột: Pessimistic Locking (Khóa bi quan) và Optimistic Locking (Khóa lạc quan).
1. Pessimistic Locking: "Thà giết nhầm còn hơn bỏ sót"
Đúng như cái tên "bi quan", cơ chế này luôn mặc định rằng: Thế nào cũng có thằng định nhảy vào sửa dữ liệu của mình, tốt nhất là khóa lại cho chắc.
Cách hoạt động: Khi bạn bắt đầu đọc dữ liệu để sửa, bạn yêu cầu Database đặt một cái khóa (Lock) lên dòng đó. Bất kỳ ai khác định đọc hoặc sửa dòng đó đều phải đứng ngoài cửa đợi cho đến khi bạn làm xong (Commit/Rollback).
Lệnh quen thuộc: SELECT ... FOR UPDATE.
Ưu điểm:
Đảm bảo tính nhất quán tuyệt đối. Tránh được các xung đột dữ liệu ngay từ đầu.
Nhược điểm:
Performance: Nếu một transaction xử lý quá lâu, nó sẽ chặn đứng tất cả các request khác, gây ra hiện tượng nghẽn cổ chai. Deadlock: Dễ xảy ra tình trạng hai ông cùng khóa dữ liệu của nhau và đợi nhau đến vô tận.
2. Optimistic Locking: "Cứ tin đi, đời sẽ đẹp"
Ngược lại, ông "lạc quan" lại nghĩ: Chắc không có ai sửa cùng lúc đâu, cứ để mọi người làm việc thoải mái, lúc nào lưu thì mình kiểm tra lại là xong.
Cách hoạt động: Không có cái khóa nào được đặt ra cả. Thay vào đó, chúng ta dùng một cột gọi là version hoặc timestamp.
Lúc bạn đọc dữ liệu, bạn lấy luôn số version (ví dụ: v1).
Lúc lưu, bạn chạy lệnh: UPDATE ... SET version = v2 WHERE id = 1 AND version = v1.
Nếu từ lúc bạn đọc đến lúc bạn lưu, có ai đó đã nhanh tay sửa trước (version đã nhảy lên v2), thì câu lệnh của bạn sẽ không cập nhật được dòng nào (Rows Affected = 0).
Ưu điểm:
Hiệu năng cực cao vì không có ai phải chờ ai. Phù hợp cho các hệ thống có lượng đọc nhiều, ghi ít hoặc ít khi xảy ra xung đột trên cùng một bản ghi.
Nhược điểm:
Nếu xung đột xảy ra thường xuyên, ứng dụng sẽ phải xử lý việc Retry (thử lại) liên tục, gây khó chịu cho người dùng hoặc tốn tài nguyên xử lý.
3. Vậy chọn phe nào?
Câu trả lời luôn là: Tùy vào Business của bạn.
Dùng Pessimistic khi: Bạn làm hệ thống ngân hàng, trừ tiền ví điện tử, hay đặt vé máy bay/flash sale. Những nơi mà một sai sót nhỏ về số dư cũng là thảm họa, và lượng tranh chấp (contention) trên một bản ghi là cực lớn.
Dùng Optimistic khi: Bạn làm CMS, Blog, quản lý thông tin User, hay các App thương mại điện tử ở quy mô vừa phải. Nơi mà khả năng hai người cùng sửa một cái Bio của một User cùng một lúc là rất thấp.
Kết luận
Không có cơ chế nào là "vô đối". Một Backend Developer xịn là người biết khi nào cần "bi quan" để bảo vệ dữ liệu và khi nào cần "lạc quan" để hệ thống bay cao.
Anh em đang dùng cơ chế nào cho dự án của mình? Có bao giờ gặp lỗi Deadlock hay Version Mismatch chưa? Chia sẻ bên dưới để mình cùng thảo luận nhé!
All rights reserved