System Design — Bài 7: Chọn database từ access pattern: ACID, index, B+Tree và LSM
Câu hỏi “SQL hay NoSQL?” thường tới quá sớm. Trước hết cần biết bạn đọc theo khóa, quét khoảng hay duyệt quan hệ; giao dịch phải giữ bất biến nào; và dữ liệu tăng ra sao. Từ đó mới có cơ sở để so storage engine và chọn sản phẩm.
Khóa học System Design: mục lục 21 bài — bạn đang đọc bài 7.
SQL, ACID và index
ACID gồm atomicity, consistency, isolation và durability: giao dịch thực hiện trọn vẹn; giữ các bất biến đã được ràng buộc đúng; kiểm soát tương tác đồng thời theo mức isolation; và bảo đảm độ bền theo cấu hình cam kết. Trong chuyển tiền, trừ một bên nhưng chưa cộng bên kia là vi phạm mục tiêu nguyên tử của giao dịch.
Index cung cấp đường truy cập tránh đọc quá nhiều dữ liệu. Nếu thường lấy đơn của một khách theo thời gian, index bắt đầu bằng khách hàng rồi thời gian có thể phù hợp. Nhưng phải kiểm tra kế hoạch thực thi; thứ tự cột và điều kiện truy vấn quyết định khả năng dùng index.
Mỗi lần ghi, database có thể phải cập nhật thêm index. Vì vậy index cần được chọn từ access pattern thực tế, không phải tạo cho mọi cột. Transaction cũng không thay chúng ta viết đúng điều kiện nghiệp vụ.
Bên trong một RDBMS
Database thường quản lý dữ liệu theo page, không đọc ổ đĩa riêng cho từng field. Buffer pool giữ các trang trong bộ nhớ để tái sử dụng. Vì vậy cùng một truy vấn có thể khác tốc độ đáng kể giữa lúc dữ liệu nóng và lúc phải đọc từ ổ đĩa.
WAL, Write-Ahead Log, ghi thông tin phục hồi trước khi các trang dữ liệu được ghi bền theo cơ chế của hệ quản trị. Sau crash, log giúp đưa dữ liệu về trạng thái hợp lệ. Mức độ bền còn phụ thuộc thời điểm flush và cấu hình xác nhận.
MVCC, Multi-Version Concurrency Control, cho phép quản lý nhiều phiên bản để phục vụ đọc theo snapshot. Trong PostgreSQL, READ COMMITTED lấy snapshot cho từng statement, còn REPEATABLE READ duy trì snapshot theo transaction. Không nên diễn giải MVCC thành “đọc không bao giờ bị ảnh hưởng bởi đồng thời”; còn có lock, xung đột và giới hạn theo isolation.
B+Tree vs LSM — đánh đổi đọc, ghi và compaction
B+Tree giữ dữ liệu theo cấu trúc cây có thứ tự, giúp tìm một khóa và quét khoảng hiệu quả. Khi ghi, ta tìm vị trí thích hợp rồi cập nhật các trang liên quan; không phải quét toàn bộ cây. Cache trang và log làm thay đổi đáng kể chi phí I/O thực tế.
LSM, Log-Structured Merge-tree, thường nhận ghi qua log và cấu trúc trong bộ nhớ, rồi flush thành các bảng bất biến trên disk. Compaction hợp nhất chúng để kiểm soát số phiên bản và tổ chức lại dữ liệu. Nó giúp gom ghi nhưng tạo chi phí đọc, ghi lại và xử lý nền.
Chúng ta cần so sánh read amplification, write amplification, dung lượng và tail latency trên workload cụ thể. Đây là so sánh storage engine; nhãn SQL hay NoSQL không đủ để kết luận hệ nào nhanh hoặc scale tốt hơn.
Chọn database nào
Hãy bắt đầu bằng câu hỏi truy vấn. Nếu chủ yếu lấy giá trị theo một khóa, mô hình key-value tự nhiên. Nếu cần tài liệu có cấu trúc linh hoạt, document database có thể phù hợp. Nếu đọc ghi theo partition và dải khóa đã biết, wide-column là một hướng. Nếu cần duyệt quan hệ nhiều bước, xem xét graph.
Đây là điểm xuất phát, không phải luật loại trừ. Các sản phẩm có tính năng giao nhau và hỗ trợ consistency khác nhau. Cần so thêm khả năng giữ bất biến, truy vấn phát sinh, hệ sinh thái và kinh nghiệm vận hành của đội.
Ví dụ lưu tin nhắn theo channel có thể phù hợp một wide-column store. Nhưng với quy mô nhỏ, database quan hệ quen thuộc vẫn có thể đáp ứng tốt. Chỉ đổi công cụ khi lợi ích được chứng minh bằng yêu cầu hoặc số đo.
Các họ database chuyên dụng
Hệ phân tích thường đọc ít cột nhưng rất nhiều dòng, nên lưu theo cột có thể giảm dữ liệu phải đọc và tăng hiệu quả nén. Điều đó khác wide-column trong cách phân loại NoSQL; hai thuật ngữ có chữ “column” nhưng nói về các khía cạnh khác nhau.
Search engine dùng inverted index để tìm tài liệu theo token rồi xếp hạng. Time-series database tối ưu các nhu cầu liên quan thời gian như khoảng truy vấn, retention và tổng hợp; cách chia chunk hay ghi dữ liệu phụ thuộc sản phẩm. Object storage lưu nội dung theo key, phù hợp nhiều loại file lớn.
Bitmap có thể biểu diễn tập và hỗ trợ đếm bằng phép toán bit: OR cho hợp, AND cho giao, sau đó đếm số bit bật. Không phải mọi database cột đều lưu mỗi cột đúng một file hay dùng cùng cơ chế index. Ta học nguyên lý, rồi kiểm tra implementation đã chọn.
Object Storage — file để đâu khi không phải database
Một object gồm nội dung và metadata, được truy cập qua key. Ứng dụng thường giữ key cùng thông tin nghiệp vụ trong database, còn byte của ảnh hoặc video nằm ở object storage. Đường đọc có thể đi qua CDN để giảm tải và độ trễ.
Ví dụ khi đăng ảnh, hệ thống cấp quyền upload có giới hạn, client gửi file tới kho rồi ứng dụng ghi nhận object đã hợp lệ. Không nên coi việc upload file và ghi bản ghi database là một transaction chung sẵn có. Cần xử lý file upload xong nhưng chưa gắn vào bài, hoặc bản ghi tham chiếu file chưa sẵn sàng.
Chi phí, consistency, thao tác cập nhật và độ bền tùy dịch vụ. Hãy kiểm tra giới hạn object, quyền truy cập, lifecycle và chi phí tải ra. Với nội dung lớn, ít sửa từng phần, đây thường là cách tách phần byte khỏi truy vấn nghiệp vụ hiệu quả.
Một access pattern dẫn tới index cụ thể
SELECT id, created_at, total
FROM orders
WHERE user_id = :user_id
ORDER BY created_at DESC, id DESC
LIMIT 20;
Index ứng viên: (user_id, created_at DESC, id DESC)
Kiểm chứng: EXPLAIN, số page đọc, p99, chi phí ghi.
Ảnh/video: Object Storage chứa byte
Database: chứa object_key, owner_id, trạng thái uploadVí dụ SQL minh họa access pattern, không phải schema hoàn chỉnh. Tie-breaker id giúp thứ tự ổn định khi nhiều bản ghi trùng thời gian. Metadata trong DB và object đã upload cần quy trình xác nhận, dọn object mồ côi và kiểm tra quyền.
Thuật ngữ cần nhớ
ACID — Atomicity, Consistency, Isolation, Durability: Bốn thuộc tính giao dịch: nguyên tử (tất cả hoặc không); nhất quán (giữ bất biến dữ liệu); cô lập (kiểm soát ảnh hưởng đồng thời); bền vững (dữ liệu đã commit tồn tại theo cam kết). Chữ C ở đây khác consistency trong định lý CAP.
WAL — Write-Ahead Log: Nhật ký ghi trước: ghi thông tin thay đổi vào log trước khi trang dữ liệu được ghi bền; dùng phục hồi sau sự cố.
MVCC — Multi-Version Concurrency Control: Kiểm soát đồng thời đa phiên bản: lưu nhiều phiên bản để người đọc dùng snapshot phù hợp; snapshot và hiện tượng đọc còn tùy mức isolation.
LSM — Log-Structured Merge-tree: Cấu trúc lưu trữ gom ghi qua bộ nhớ rồi các tệp có thứ tự; compaction hợp nhất dữ liệu, đổi chi phí ghi nhanh lấy công việc đọc/gộp nền.
OLAP — Online Analytical Processing: Xử lý phân tích trực tuyến: truy vấn tổng hợp trên nhiều dữ liệu, thường phục vụ báo cáo và phân tích thay vì thao tác từng giao dịch.
Bài tập tự thực hành
Thiết kế lưu ảnh đại diện cùng metadata.
Gợi ý kiểm tra lời giải
Object storage cho byte, DB cho metadata; xử lý upload dở và object mồ côi; kiểm tra quyền.
Tự kiểm tra sau bài học
Truy vấn và thứ tự cột index khớp nhau.
Phân biệt atomicity, isolation và durability.
Không suy hiệu năng từ nhãn SQL/NoSQL; xét engine và workload.
Đọc thêm từ tài liệu gốc
PostgreSQL: Transaction Isolation
Tiếp tục lộ trình
Bài trước — Đường đi của request: DNS, CDN, Load Balancer và Gateway
Bài tiếp — Scale dữ liệu: replication, partition và sharding
Site Admin
Engineer and writer. Building things with TypeScript and distributed systems.
Bình luận (0)
Bạn cần đăng nhập bằng Google để bình luận.
Hãy là người bình luận đầu tiên.