ID là một khái niệm rất quen thuộc đối với developer, được sử dụng để định danh một đối tượng cụ thể. Thao tác với ID nghe có vẻ đơn giản nhưng khi nhúng tay vào các hệ thống có khả năng scale lớn sẽ phát sinh khá nhiều bài toán hóc búa.
ID tự động tăng
- Với những bạn làm việc với database nhiều, khái niệm auto-increment primary key sẽ không còn xa lạ. Lấy ví dụ xây dựng chức năng đăng bài đơn giản, cách phổ biến để thiết kế database là tạo một table posts gồm các column:
- id: unique id cho mỗi bài post
- author: khóa ngoại trỏ tới bảng users
- và những field content, …
Nếu chỉ có một server database và một luồng ghi vào CSDL thì việc sẽ nhẹ nhàng, khởi tạo id chạy từ 0, khi có bài viết mới được đăng thì cho id tăng dần lên. Bài toán sẽ khó hơn bạn có nhiều hơn một luồng ghi, bạn phải đảm bảo không xảy ra hai bài viết khác nhau nhưng lại có cùng một id. May mắn là database hiện tại có các cơ chế về locking để đảm bảo tính Atomic (nhất quán) cho dữ liệu.
Scale nhiều data stores
Bài toán ID tự động tăng sẽ hoạt động trơn tru khi bạn có một server duy nhất. Trong tương lai, sản phẩm của bạn ngày càng phát triển, traffic tăng và database phình to, bạn chọn cách scale database ra nhiều servers. Vấn đề phát sinh khi mỗi server lại có một bộ ID riêng và bạn cần đảm bảo tất cả các bài viết trên hệ thống databases phân tán là duy nhất. Có một vài cách giải quyết như sau:
1. Ghi tập trung (Centralized writes)
Bạn chỉ định một database làm leader đảm nhận các request ghi (write) dữ liệu, các database còn lại sẽ đóng vai trò replica từ leader và phục vụ nhu cầu đọc dữ liệu (read). Mô hình trên còn được gọi là master-slave (hoặc primary-replica). Tuy nhiên, nhược điểm ở mô hình này chính là nút thắt cổ chai (bottleneck) xảy ra ở database master nếu hệ thống của bạn cần phục vụ việc ghi nhiều hơn là đọc dữ liệu nên cần phải cân nhắc.
2. Tạo ID tập trung (Centralized ID generation)
Ngoài cách trên, hệ thống của bạn được phép ghi vào bất kì database nào, nhưng trước đó, cần một thao tác Gen-ID để đảm bảo id của bài viết là duy nhất. Dù phương pháp này cho phép chúng ta ghi vào nhiều database, nhưng vẫn phát sinh bottleneck tại thao tác Gen-ID.
3. Chọn ngẫu nhiên từ tập hợp lớn (Pick randomly from a large range)
Thay vì sử dụng ID tăng dần, bạn còn một giải pháp khác là chọn ngẫu nhiên ID từ một tập hợp số thật lớn, phổ biến như UUID để đảm bảo tính duy nhất của nó. Nhược điểm của phương pháp này nằm ở việc ID chọn có thể thể lớn và không theo trình tự.
4. Mã hóa phân vùng ID (Encode the partition in the ID)
Thay thế cho giải pháp chọn ID từ tập số lớn bên trên, bạn có tạo ID bằng cách đính kèm với tiền tố của partition chẳng hạn như 01-123, 02-123. Giải pháp này cho phép bạn sử dụng ID tự tăng mà vẫn đảm bảo không bị trùng ID giữa các database server.
Tóm lại còn nhiều giải pháp khác, tùy vào từng trường hợp mà bạn cần chọn cách giải quyết hợp lý, việc đảm bảo tính duy nhất cho ID trên hệ thống cần mở rộng cao cũng sẽ là một thách thức cho bạn.
Mời các bạn cùng đọc bài viết sau.
(by duyquang)