[System Design] P7 - SQL & NoSQL

I. Từ Lưu trữ Đơn giản đến Cơ sở dữ liệu Phức tạp
Hành trình quản lý dữ liệu ứng dụng thường bắt đầu bằng các phương pháp sơ khai, phát triển thành các hệ thống phức tạp hơn khi yêu cầu tăng lên. Hiểu được sự phát triển này làm nổi bật các vấn đề cơ bản mà các database
hiện đại được thiết kế để giải quyết.
A. Những Hạn chế của Lưu trữ Cơ bản
Trong giai đoạn đầu phát triển ứng dụng, dữ liệu có thể được hardcode
trực tiếp vào các trang HTML
. Tuy nhiên nhược điểm của nó là việc hoàn toàn không thực tế đối với dữ liệu động cần được cập nhật hoặc quản lý.
Một bước tiến là sử dụng các công cụ sẵn có như phần mềm bảng tính (spreadsheet
), chẳng hạn như Microsoft Excel
. Đối với các ứng dụng nhỏ, đơn giản với dữ liệu hạn chế và ít người dùng, một spreadsheet
ban đầu có thể đủ dùng. Tuy nhiên, những hạn chế của việc lưu trữ dựa trên spreadsheet
nhanh chóng trở nên rõ ràng khi ứng dụng trưởng thành.
Sự tiến triển từ dữ liệu hardcoded
và spreadsheets
sang các hệ thống có cấu trúc hơn không chỉ là vấn đề sở thích mà còn là phản ứng trực tiếp đối với những hạn chế cố hữu này. Khi các ứng dụng yêu cầu truy cập đồng thời, lưu trữ dữ liệu đáng tin cậy, truy vấn hiệu quả trên các tập dữ liệu lớn và khả năng mở rộng, nhu cầu về một Hệ thống Quản lý Cơ sở dữ liệu (Database Management System
- DBMS
) chuyên dụng trở nên không thể phủ nhận. Các hệ thống này được thiết kế đặc biệt để giải quyết những thiếu sót của việc lưu trữ dựa trên tệp đơn giản hơn.
B. Giới thiệu về Cơ sở dữ liệu (Databases
)
Về cơ bản, database
là một tập hợp dữ liệu có tổ chức, được cấu trúc để cho phép quản lý, lưu trữ, truy xuất và thao tác hiệu quả. Nó cung cấp một cách có hệ thống để xử lý thông tin thông qua một tập hợp các hoạt động được xác định.
Các hoạt động cơ bản nhất là: Create, Read, Update và Delete và Search. Các ứng dụng hiện đại đặt ra những yêu cầu đáng kể đối với database
nền tảng của chúng. Một số thuộc tính chính rất được mong đợi, mặc dù cần có sự đánh đổi nhất định trong thiết kế hệ thống:
Tính Sẵn sàng Cao (
High Availability
): Hệ thốngdatabase
phải duy trì hoạt động và có thể truy cập được cho người dùng ngay cả khi đối mặt với các sự cố ảnh hưởng đến hệ thống.Tính Nhất quán Mạnh (
Strong Consistency
): Sau khi một thao tác cập nhật hoàn tất, tất cả các lần đọc tiếp theo phải trả về giá trị đã cập nhật. Trong một hệ thống phân tán, điều này có nghĩa là tất cả các bản sao dữ liệu có thể truy cập đều phản ánh các ghi (writes
) thành công mới nhất.Khả năng Mở rộng Cao (
High Scalability
): Hệ thống phải có khả năng xử lý một cách trơn tru sự tăng trưởng về khối lượng dữ liệu, tốc độ giao dịch và tải người dùng mà không làm suy giảm đáng kể hiệu suất.Hiệu suất và Tốc độ (
Performance & Speed
): Các hoạt độngdatabase
, đặc biệt là đọc (read
) và ghi (write
) phải thực thi nhanh chóng với độ trễ thấp đáp ứng trải nghiệm người dùng.
Điều quan trọng là phải nhận ra rằng những thuộc tính mong muốn này thường liên kết với nhau và đôi khi mâu thuẫn dẫn đến việc cần sự đánh đổi nhất định trong thiết kế database
(Định lý CAP).
II. Thế giới Cơ sở dữ liệu Quan hệ (Relational Databases
- SQL
)
Relational databases
, thường được truy vấn bằng Ngôn ngữ Truy vấn Cấu trúc (Structured Query Language - SQL), đã là mô hình thống trị trong quản lý dữ liệu trong nhiều thập kỷ. Cấu trúc và các đảm bảo giao dịch của chúng cung cấp một nền tảng vững chắc cho nhiều ứng dụng.
A. Mô hình Quan hệ (Relational Model
)
Một Hệ thống Quản lý Cơ sở dữ liệu Quan hệ (Relational Database Management System
- RDBMS
) tổ chức dữ liệu thành các bảng (tables
), chính thức được gọi là quan hệ (relations
).
Mỗi table
bao gồm các hàng (rows
- tuples
), đại diện cho các bản ghi riêng lẻ, và các cột (columns
- attributes
), đại diện cho các thuộc tính cụ thể của các bản ghi đó
Ví dụ, một database
đại học có thể có table
Lecturers với các columns
như LID (Lecturer ID) và LectureName, và một table
Sessions với các columns
như LID, SID (Student ID), và SessionDate, liên kết giảng viên với các buổi học của sinh viên.
Trong lịch sử, đặc biệt là khi chi phí lưu trữ đắt đỏ hơn và khối lượng dữ liệu nhỏ hơn, một động lực chính cho mô hình quan hệ là tối ưu hóa lưu trữ và giảm dư thừa dữ liệu. Điều này đạt được thông qua một quá trình gọi là chuẩn hóa (normalization
).
Normalization
bao gồm việc chia nhỏ dữ liệu thành nhiều tables
, mỗi table
tập trung vào một thực thể hoặc khái niệm duy nhất, và sử dụng các khóa (keys
) để xác định mối quan hệ giữa chúng. Điều này giảm thiểu việc lưu trữ dữ liệu dư thừa; ví dụ, tên của một giảng viên chỉ được lưu trữ một lần trong table
Lecturers, thay vì được lặp lại cho mỗi buổi học mà họ thực hiện.
Mặc dù normalization
rất hiệu quả về lưu trữ và đảm bảo tính nhất quán dữ liệu khi có sửa đổi, nó có một hệ quả đáng kể: việc truy xuất một cái nhìn hoàn chỉnh về thông tin liên quan thường yêu cầu kết hợp dữ liệu từ nhiều tables
bằng cách sử dụng các phép toán JOIN
. Khi khối lượng dữ liệu và độ phức tạp của truy vấn tăng lên, các phép toán JOIN
này có thể trở thành một nút thắt hiệu suất chính, một thách thức quan trọng mà các mô hình database
thay thế sau này đã tìm cách giải quyết.
B. Thuộc tính ACID
: Đảm bảo Độ tin cậy
Một đặc điểm xác định của hầu hết các RDBMS
truyền thống là việc tuân thủ các thuộc tính ACID
, đảm bảo độ tin cậy của các giao dịch (transactions
). Một transaction
là một chuỗi các hoạt động database
được thực hiện như một đơn vị công việc logic duy nhất.
ACID
là từ viết tắt của Atomicity
, Consistency
, Isolation
, và Durability
.
Tính Nguyên tử (
Atomicity
- Tất cả hoặc không gì cả): Thuộc tính này đảm bảo rằng mộttransaction
được coi là một đơn vị không thể chia cắt. Hoặc tất cả các hoạt động trongtransaction
được hoàn thành thành công và đượccommit
vàodatabase
, hoặc không có hoạt động nào được thực hiện. Nếu bất kỳ phần nào củatransaction
thất bại (do lỗi, sự cố hệ thống, v.v.), toàn bộtransaction
sẽ đượcrollback
, đưadatabase
về trạng thái trước khitransaction
bắt đầu. Một phép loại suy phổ biến là chuyển khoản ngân hàng: việc trừ tiền từ tài khoản A và cộng vào tài khoản B phải xảy ra cùng nhau như một đơn vịatomic
duy nhất. Nếu việc ghi có vào B thất bại sau khi ghi nợ từ A,atomicity
đảm bảo việc ghi nợ sẽ được hoàn tác.Tính Nhất quán (
Consistency
- Bảo toàn Trạng thái):Consistency
đảm bảo rằng mộttransaction
đưadatabase
từ một trạng thái hợp lệ này sang một trạng thái hợp lệ khác.Database
có các quy tắc được xác định trước (ràng buộc -constraints
,triggers
, kiểu dữ liệu) định nghĩa tính hợp lệ. Mộttransaction
phải đảm bảo rằng khi hoàn thành (nếu thành công), tất cả các quy tắc này đều được thỏa mãn. Ví dụ, nếu mộtdatabase
ngân hàng có quy tắc rằng tổng số dư của tất cả các tài khoản phải không đổi, mộttransaction
chuyển khoản phải bảo toàn tổng số này; nếu không thể,transaction
sẽ thất bại và trạng tháidatabase
vẫn nhất quán. Một phép loại suy là đảm bảo số lượt thích của một album ảnh khớp với số lượng mục nhật ký liệt kê những người đã thích ảnh đó;consistency
ngăn chặn sự không khớp.Tính Cô lập (
Isolation
- Kiểm soát Đồng thời): Trong các hệ thống nơi nhiềutransactions
có thể thực thi đồng thời,isolation
đảm bảo rằng cáctransactions
này không can thiệp lẫn nhau theo những cách không mong muốn. Hiệu quả của cáctransactions
đồng thời phải giống như thể chúng được thực thi nối tiếp nhau (tuần tự -serially
). Nếu không cóisolation
, một số dị thường có thể xảy ra:Đọc bẩn (
Dirty Reads
): Mộttransaction
đọc dữ liệu đã được sửa đổi bởi mộttransaction
khác nhưng chưa đượccommit
. Nếutransaction
sửa đổi bịrollback
,transaction
đầu tiên đã đọc dữ liệu "bẩn" hoặc không hợp lệ. (Phép loại suy: Nhìn trộm vào một căn phòng trong khi ai đó vẫn đang dọn dẹp; trạng thái cuối cùng chưa được ổn định).Đọc không lặp lại (
Non-Repeatable Reads
): Mộttransaction
đọc một phần dữ liệu, mộttransaction
đồng thời khác sửa đổi hoặc xóa dữ liệu đó vàcommit
,transaction
đầu tiên đọc lại cùng dữ liệu đó, nhận được một giá trị khác. (Phép loại suy: Đếm táo, ai đó thêm/bớt một quả, đếm lại cho ra một số khác).Đọc Bóng ma (
Phantom Reads
): Mộttransaction
thực hiện một truy vấn dựa trên một số điều kiện, mộttransaction
đồng thời khác chèn dữ liệu mới thỏa mãn điều kiện đó vàcommit
,transaction
đầu tiên thực thi lại truy vấn của mình, tìm thấy các hàng "bóng ma" mới. (Phép loại suy: Kiểm tra một giỏ táo, sau đó phát hiện ra cam xuất hiện trong lần kiểm tra tiếp theo).Mất cập nhật (
Lost Updates
): Haitransactions
đọc cùng một mục dữ liệu, cả hai đều sửa đổi nó dựa trên giá trị đã đọc, sau đó ghi lại. Lần ghi thứ hai ghi đè lên lần ghi thứ nhất, thực sự làm mất bản cập nhật được thực hiện bởitransaction
đầu tiên. (Phép loại suy: Hai nghệ sĩ vẽ chồng lên tác phẩm của nhau trên cùng một tấm canvas). Các hệ thốngdatabase
triển khaiisolation
bằng cách sử dụng các cơ chế như khóa (locking
- kiểm soát bi quan, nơi tài nguyên bị khóa để ngăn xung đột) hoặc kiểm soát đồng thời đa phiên bản (multi-version concurrency control
-MVCC
) (kiểm soát lạc quan, nơi các phiên bản khác nhau của dữ liệu được duy trì). Các mứcisolation
khác nhau (ví dụ:Read Uncommitted
,Read Committed
,Repeatable Read
,Serializable
) cung cấp các mức độ bảo vệ khác nhau chống lại các dị thường này, đánh đổi các đảm bảoconsistency
để có được lợi ích vềperformance
tiềm năng.
Tính Bền vững (
Durability
- Tính bền bỉ): Một khi mộttransaction
đã đượccommit
thành công, những thay đổi của nó sẽ được thực hiện vĩnh viễn trongdatabase
. Những thay đổi này phải tồn tại sau các sự cố hệ thống tiếp theo, chẳng hạn như mất điện hoặc sự cố (crashes
). Điều này thường đạt được bằng cách sử dụng các kỹ thuật như ghi các thay đổi vào nhật ký giao dịch (transaction logs
-Write-Ahead Logging
hoặcWAL
) trước khi áp dụng chúng vào các tệp dữ liệu chính, đảm bảo rằng các quy trình phục hồi có thể khôi phục các thay đổi đãcommit
sau một sự cố. Phép loại suy là lưu tiến trình trong một trò chơi điện tử; một khi đã lưu, tiến trình vẫn tồn tại ngay cả khi trò chơi bịcrash
sau đó.
Các đảm bảo ACID
tạo thành một hợp đồng cơ bản giữa database
và nhà phát triển ứng dụng. Bằng cách dựa vào các thuộc tính này, các nhà phát triển có thể đơn giản hóa logic ứng dụng, vì họ không cần phải xây dựng các cơ chế phức tạp trong chính ứng dụng để xử lý các lỗi cục bộ hoặc các tình huống concurrency control
phức tạp. Hệ thống database
đảm nhận trách nhiệm này, điều đặc biệt quan trọng đối với các ứng dụng đòi hỏi data integrity
cao, chẳng hạn như hệ thống tài chính, nền tảng thương mại điện tử và quản lý hàng tồn kho.
III. Cơ sở dữ liệu Phi Quan hệ (Non-Relational Databases
- NoSQL
)
Trong khi relational databases
cung cấp các đảm bảo mạnh mẽ và một cách tiếp cận được chuẩn hóa, với sự trỗi dậy của các ứng dụng web quy mô lớn, big data
, và nhu cầu xử lý dữ liệu linh hoạt hơn đã dẫn đến sự phát triển và áp dụng các database
phi quan hệ, thường được nhóm lại dưới thuật ngữ "NoSQL
".
A. Giải quyết các Hạn chế của RDBMS
NoSQL databases
xuất hiện chủ yếu để giải quyết các hạn chế được nhận thấy của các RDBMS
truyền thống:
RDBMS truyền thống | NoSQL databases | |
Khả năng mở rộng (Scalability ) | Các RDBMS truyền thống được thiết kế chủ yếu cho vertical scaling (tăng sức mạnh cho một máy chủ duy nhất bằng cách thêm CPU, RAM, bộ nhớ). Tuy nhiên các máy chủ đều sẽ có giới hạn về vật lý và chi phí. | NoSQL thường được thiết kế từ đầu cho horizontal scaling (phân phối dữ liệu và tải trên nhiều máy chủ - commodity servers ), mang lại khả năng mở rộng không giới hạn. |
Tính linh hoạt (Flexibility ) | SQL yêu cầu định nghĩa trước cấu trúc dữ liệu chặt chẽ. Việc thay đổi cấu trúc như thêm cột mới có thể rất phức tạp và ảnh hưởng đến toàn bộ hệ thống. | NoSQL cho phép lưu trữ dữ liệu với cấu trúc linh hoạt (không yêu cầu định nghĩa trước), thậm chí mỗi bản ghi (document, item) có thể có cấu trúc khác nhau |
Hiệu suất/Tính sẵn sàng (Performance/Availability ) | Để đạt tốc độ cao cho các tác vụ đọc/ghi đơn giản với lượng truy cập khổng lồ, NoSQL thường đơn giản hóa mô hình bằng cách phi chuẩn hóa (denormalization) (lưu dữ liệu liên quan cùng một chỗ, tránh phải "join" như SQL) và được thiết kế cho môi trường phân tán (nhiều máy chủ). Nhiều hệ thống NoSQL chấp nhận việc đạt được tính sẵn sàng (Availability) hơn là tính nhất quán mạnh (Strong Consistency) khi có sự cố mạng (khái niệm BASE). |
B. Các Khái niệm Cốt lõi và Lợi ích
NoSQL databases
bao gồm một số khái niệm chung và lợi ích tiềm năng:
Mô hình Dữ liệu Linh hoạt / Thiết kế Không Schema (
Flexible Data Models / Schema-less Design
):Đặc điểm lớn nhất là việc bỏ đi
schema
dạng bảng cứng nhắc củaRDBMS
.NoSQL databases
sử dụng các mô hình dữ liệu khác nhau (key-value
,document
,column-family
,graph
) cho phép các cấu trúc động. Tính chất "schema-less
" hoặc "schema-flexible
" này cho phép các ứng dụng lưu trữ dữ liệu mà không ép buộc nó vào cáctables
được định nghĩa trước.Ví dụ, một sản phẩm thương mại điện tử có thể có hàng trăm hoặc hàng nghìn thuộc tính, nhiều thuộc tính trong số đó chỉ áp dụng cho các loại sản phẩm cụ thể. Việc biểu diễn điều này một cách hiệu quả trong một
schema
RDBMS
cứng nhắc có thể là một thách thức, trong khi mộtdocument database
có thể dễ dàng lưu trữ tập hợp các thuộc tính duy nhất của mỗi sản phẩm trongdocument
của riêng nó.
Mở rộng Ngang (
Horizontal Scaling
-Scalability
):Mục tiêu thiết kế chính của nhiều hệ thống
NoSQL
là khả năng mở rộng theo chiều ngang.Bằng cách phân vùng (
partitioning
-sharding
) dữ liệu trên nhiều máy chủ, các hệ thống này có thể xử lý các tập dữ liệu khổng lồ và lưu lượng tải truy cập cao mà sẽ làm quá tải một máy chủRDBMS
duy nhất. Việc thêm dung lượng thường liên quan đến việc thêm nhiều máy chủ hơn vàocluster
.
Truy vấn Nhanh (
Fast Queries
- Hiệu suất cho các Mẫu Cụ thể):NoSQL databases
thường đạt được hiệu suất cao cho các mẫu truy vấn nhất định bằng cách tối ưu hóa tính cục bộ của dữ liệu. Điều này thường liên quan đến việc phi chuẩn hóa (denormalization
), nơi dữ liệu liên quan được lưu trữ cùng nhau trong một bản ghi duy nhất (ví dụ: nhúng chi tiết đơn hàng vào trong mộtdocument
đơn hàng) thay vì được chia nhỏ trên nhiềutables
đã chuẩn hóa. Điều này tránh được nhu cầu về các phép toánJOIN
tốn kém trong quá trình đọc, dẫn đến việc truy xuất dữ liệu nhanh hơn cho các mẫu truy cập phổ biến.Tuy nhiên, cách tiếp cận này đại diện cho một sự đánh đổi đáng kể. Trong khi
relational databases
cố gắng loại bỏ sự dư thừa thông quanormalization
để đạt hiệu quả lưu trữ và tính nhất quán,NoSQL databases
thường chấp nhận sự dư thừa thông quadenormalization
để tối ưu hóa hiệu suất đọc. Hậu quả là các cập nhật có thể yêu cầu sửa đổi dữ liệu ở nhiều nơi, làm tăng độ phức tạp ghi và tạo ra khả năng không nhất quán tạm thời nếu việc cập nhật không được quản lý cẩn thận trên tất cả các bản sao dư thừa
Tính Sẵn sàng Cao (
High Availability
):- Nhiều
NoSQL databases
được phân tán và tích hợp các cơ chế sao chép (replication
), làm cho chúng có khả năng phục hồi tốt hơn đối với các lỗi máy chủ riêng lẻ. Dữ liệu thường được sao chép trên nhiềunode
, đảm bảo rằng hệ thống có thể tiếp tục hoạt động ngay cả khi một sốnode
không khả dụng.
- Nhiều
C. Các Loại Chính của NoSQL Databases
Thuật ngữ "NoSQL
" bao gồm một số loại database
riêng biệt được tối ưu hóa cho các cấu trúc dữ liệu và trường hợp sử dụng khác nhau như:
- Kho Lưu trữ Khóa-Giá trị (
Key-Value Stores
):
Mô hình: Đây là loại đơn giản nhất, giống như một cuốn từ điển hoặc tủ giữ đồ ở siêu thị. Bạn có một cái khóa (key) duy nhất (như số thẻ giữ đồ) và nó trỏ đến một giá trị (value) (cái túi đồ của bạn). Value có thể là bất cứ thứ gì: văn bản, số, ảnh, JSON.
Ưu điểm:
Siêu nhanh cho các thao tác đơn giản như lấy giá trị, lưu giá trị và xóa giá trị theo khóa.
Dễ mở rộng, phù hợp cho dữ liệu đơn giản.
Nhược điểm:
Chỉ truy vấn được bằng khóa. Khó truy vấn dựa trên nội dung của value hoặc mối quan hệ giữa các khóa. Bạn không thể dễ dàng hỏi "Hãy tìm tất cả những cái túi đồ màu đỏ" mà chỉ có thể hỏi "Cái túi ứng với số thẻ 123 là gì?".
Không phù hợp cho dữ liệu phức tạp cần mối quan hệ.
Trường hợp Sử dụng:
Caching
(lưu trữ dữ liệu được truy cập thường xuyên trong bộ nhớ), quản lý session đăng nhập web, hệ thống đấu giá thời gian thực, bảng xếp hạng…Ví dụ:
Redis
,Memcached
,Amazon DynamoDB
(cũng phù hợp với mô hìnhdocument
).
- Cơ sở dữ liệu Tài liệu (
Document Databases
):
Mô hình:
Lưu dữ liệu dưới dạng các tài liệu (documents), thường là định dạng JSON hoặc BSON.
Các document được nhóm vào các bộ sưu tập (collections) (tương tự table trong SQL) nhưng điểm đặc biệt là việc các document trong cùng collection không nhất thiết phải có cấu trúc giống hệt nhau.
{ "Mã sách": "001", "Tên": "Harry Potter", "Giá": 20, "Thông tin thêm": { "Tác giả": "J.K. Rowling", "Đánh giá": 4.5 } }
Ưu điểm:
Linh hoạt về cấu trúc (schema).
Dễ dàng ánh xạ với các đối tượng trong lập trình.
Cho phép truy vấn dựa trên nội dung bên trong document (ví dụ: tìm tất cả sản phẩm có giá > 1 triệu và màu "Đen").
Nhược điểm:
Các cấu trúc lồng nhau quá phức tạp có thể trở nên khó quản lý và truy vấn hiệu quả.
Có thể kém hiệu quả cho các truy vấn yêu cầu mối quan hệ phức tạp giữa nhiều
documents
.
Trường hợp Sử dụng: Quản lý nội dung (blog, bài báo), danh mục sản phẩm E-commerce, hồ sơ người dùng, dữ liệu ứng dụng di động, logging.
Ví dụ:
MongoDB
,Couchbase
,CouchDB
,Amazon DynamoDB
.
- Kho Lưu trữ Cột Rộng (
Wide-Column Stores
):
Mô hình:
Dữ liệu được theo bảng, cột, dòng, nhưng khác SQL, mỗi hàng có thể có các cột khác nhau, và cột được nhóm thành "họ cột" (column families).
Rất tốt cho dữ liệu thưa (sparse) - tức là nhiều ô có thể bị trống.
Ví dụ việc lưu thông tin cảm biến IoT:
Row 1:
{Cảm biến_001, Nhiệt độ: 25, Độ ẩm: 60}
Row 2:
{Cảm biến_002, Nhiệt độ: 30}
Ưu điểm:
Khả năng mở rộng cực tốt cho dữ liệu lớn, đặc biệt cho việc ghi dữ liệu rất nhiều
Hiệu quả khi truy vấn một số cột cụ thể.
Nhược điểm:
Mô hình hóa dữ liệu phức tạp hơn.
Ngôn ngữ truy vấn có thể không mạnh mẽ bằng SQL cho các phép
JOIN
tùy ý.
Trường hợp Sử dụng:
Dữ liệu chuỗi thời gian: Lưu nhiệt độ, độ ẩm từ cảm biến IoT.
Phân tích big data: Xử lý dữ liệu lớn từ mạng xã hội hoặc log hệ thống.
Ví dụ:
Apache Cassandra
,Google Cloud Bigtable
,Apache HBase
.
- Cơ sở dữ liệu Đồ thị (
Graph Databases
):
Mô hình: Dữ liệu gồm các nút (nodes) (đại diện cho thực thể, ví dụ: người, sản phẩm) và các cạnh (edges) (đại diện cho mối quan hệ giữa các nút, ví dụ: "Bạn bè với", "Đã mua”. Cả nút và cạnh đều có thể có thuộc tính. Phù hợp cho dữ liệu có nhiều kết nối và có các mối quan hệ phức tạp.
Ưu điểm:
Rất hiệu quả cho việc duyệt qua các mối quan hệ phức tạp (ví dụ: tìm bạn của bạn bè, đường đi ngắn nhất).
Mô hình hóa rất tự nhiên cho dữ liệu có tính kết nối cao.
Nhược điểm:
Có thể không hiệu quả bằng các mô hình khác đối với các truy vấn yêu cầu quét hoặc tổng hợp các thuộc tính trên số lượng lớn
nodes
hoặcedges
mà không cần duyệt qua các mối quan hệ.Việc mở rộng có thể đặt ra những thách thức, đặc biệt đối với các truy vấn liên quan đến việc duyệt phức tạp trên dữ liệu phân tán.
Có thể là quá mức cần thiết đối với các tập dữ liệu không có độ phức tạp về mối quan hệ đáng kể.
Trường hợp Sử dụng: Mạng xã hội (quản lý kết nối), công cụ đề xuất (đề xuất các mục dựa trên hành vi người dùng liên quan), phát hiện gian lận (xác định các mẫu kết nối đáng ngờ), ánh xạ cơ sở hạ tầng mạng và CNTT, đồ thị tri thức, quản lý danh tính và truy cập.
Ví dụ:
Neo4j
,Amazon Neptune
,ArangoDB
(multi-model),OrientDB
(multi-model).
Sự đa dạng trong NoSQL
nhấn mạnh rằng nó không phải là một công nghệ duy nhất mà là một tập hợp các cách tiếp cận được thiết kế để giải quyết các vấn đề mà mô hình quan hệ truyền thống có thể kém phù hợp hơn. Sự lựa chọn đòi hỏi phải hiểu cấu trúc dữ liệu cụ thể và các mẫu truy cập của ứng dụng.
D. Các Hạn chế Tiềm ẩn
Mặc dù có những lợi thế, NoSQL
cũng đi kèm với những hạn chế tiềm ẩn:
Mô hình Nhất quán (
Consistency Models
):NoSQL thường nới lỏng các yêu cầu nhất quán mạnh
ACID
của SQL để ưu tiên high availability và partition tolerance.Chúng thường cung cấp "
eventual consistency
", nghĩa là, nếu bạn ghi dữ liệu mới, không phải tất cả các bản sao trên các máy chủ sẽ được cập nhật ngay lập tức. Sẽ có một độ trễ nhỏ, nhưng cuối cùng thì tất cả các bản sao sẽ trở nên nhất quán.Ví dụ: Bạn đổi ảnh đại diện Facebook. Có thể trong vài giây đầu, một số bạn bè vẫn thấy ảnh cũ, một số thấy ảnh mới. Nhưng sau một lúc, mọi người sẽ thấy ảnh mới.
Eventual consistency có thể được chấp nhận được với nhiều ứng dụng như mạng xã hội, nhưng không phù hợp với những nơi yêu cầu tính nhất quán tức thì như hệ thống ngân hàng.
Việc lập trình với eventual consistency cũng phức tạp hơn.
Triết lý BASE: Thường được dùng để mô tả các hệ thống này: Basically Available (Cơ bản là Sẵn sàng), Soft state (Trạng thái mềm - có thể thay đổi theo thời gian), Eventually consistent (Nhất quán Cuối cùng). Đây là sự đánh đổi so với ACID của SQL.
Lưu ý: Một số hệ thống NoSQL hiện đại cũng cung cấp tùy chọn để có mức độ nhất quán mạnh hơn, thậm chí tuân thủ ACID.
Tiêu chuẩn hóa (
Standardization
):- NoSQL không có một ngôn ngữ truy vấn chung như SQL. Mỗi loại NoSQL (thậm chí mỗi sản phẩm) có thể có API và ngôn ngữ truy vấn riêng (ví dụ: MongoDB dùng MQL, Cassandra dùng CQL...). Điều này gây khó khăn khi chuyển đổi giữa các hệ thống NoSQL khác nhau (vendor lock-in), yêu cầu lập trình viên phải học nhiều giao diện khác nhau.
Độ phức tạp Giao dịch (
Transaction Complexity
):- NoSQL không mạnh trong các giao dịch (transaction) phức tạp (như chuyển tiền ngân hàng, cần cập nhật nhiều bảng cùng lúc), đòi hỏi xử lý nhiều logic ở phía ứng dụng so với SQL.
Độ trưởng thành (
Maturity
):- Các cơ sở dữ liệu SQL đã tồn tại hàng thập kỷ, có nhiều công cụ hỗ trợ, tài liệu và chuyên gia, trong khi đó, các cơ sở dữ liệu NoSQL mới hơn, nên một số hệ thống (như graph databases) có thể thiếu tài liệu hoặc cộng đồng hỗ trợ.
IV. SQL vs. NoSQL: Phân tích So sánh
A. Xem xét lại các Điểm Khác biệt Cốt lõi
Dựa trên các thảo luận trước đó, các điểm khác biệt cốt lõi giữa SQL và NoSQL điển hình có thể được tóm tắt như sau:
SQL | NoSQL | |
Mô hình Dữ liệu | Dữ liệu được lưu trong bảng (tables) với hàng (rows) và cột (columns) được định nghĩa rõ ràng. Mỗi bảng đại diện cho một loại thực thể (như "Khách hàng", "Sản phẩm"). | Dữ liệu được lưu theo nhiều cách khác nhau, tùy thuộc vào loại NoSQL như Key-Value, Document, Wide-Column, Graph |
Schema | Yêu cầu schema cố định với định nghĩa về các cột của bảng, và mọi hàng phải tuân theo cấu trúc đó. | Schema linh hoạt hoặc không cần schema. Bạn có thể thêm dữ liệu mới mà không cần định nghĩa trước. |
Khả năng mở rộng (Scalability) | Chủ yếu mở rộng dọc (vertical scaling) | Mở rộng ngang (horizontal scaling) |
Tính nhất quán (Consistency ) | Tuân thủ ACID (Atomicity, Consistency, Isolation, Durability), đảm bảo dữ liệu luôn nhất quán ngay lập tức. | Thường dùng BASE (Basically Available, Soft state, Eventual consistency), ưu tiên tính sẵn sàng và có thể chấp nhận độ trễ nhỏ trong đồng bộ dữ liệu không (Eventual Consistency) |
Ngôn ngữ Truy vấn | Dùng ngôn ngữ chuẩn hóa là SQL. | Mỗi loại, mỗi sản phẩm có thể có ngôn ngữ hoặc cách truy vấn riêng |
Loại dữ liệu | Tốt cho dữ liệu có cấu trúc (structured), có mối quan hệ chặt chẽ như bảng lương, tài khoản ngân hàng. | Phù hợp với dữ liệu không có cấu trúc (unstructured), bán cấu trúc (semi-structured), hoặc dữ liệu rất đa dạng. |
Ngày nay, ranh giới giữa SQL và NoSQL không còn rõ ràng như trước:
SQL đang học hỏi NoSQL: Nhiều hệ quản trị CSDL SQL hiện đại (như PostgreSQL, SQL Server) đã bổ sung các tính năng giống NoSQL, ví dụ như hỗ trợ lưu trữ và truy vấn dữ liệu dạng JSON trực tiếp trong bảng, cải thiện khả năng nhân bản (replication) và phân mảnh (partitioning) dữ liệu.
NoSQL đang học hỏi SQL: Ngược lại, một số CSDL NoSQL đang cố gắng cung cấp các tính năng mạnh mẽ của SQL như giao dịch đảm bảo ACID, hoặc cung cấp các giao diện truy vấn gần giống SQL để dễ tiếp cận hơn.
Sự xuất hiện của "NewSQL" / "Distributed SQL": Có một thế hệ CSDL mới (ví dụ: CockroachDB, YugabyteDB, Google Spanner) ra đời với mục tiêu kết hợp những gì tốt nhất của cả hai thế giới: khả năng mở rộng ngang và tính sẵn sàng cao của NoSQL cùng với sự nhất quán mạnh mẽ và đảm bảo giao dịch (ACID) của SQL truyền thống
Bảng 1: So sánh SQL vs. NoSQL ở Mức độ Cao
Tính năng | SQL (Quan hệ) | NoSQL (Phi quan hệ - Xu hướng chung) |
Data Model | Tables (Rows, Columns) | Document, Key-Value, Wide-Column, Graph |
Schema | Predefined, Rigid | Dynamic, Flexible |
Primary Scalability | Vertical (Scale-Up) | Horizontal (Scale-Out) |
Consistency Model | Strong (ACID) | Tunable (Often Eventual/BASE, some offer ACID) |
Data Type Focus | Structured | Unstructured, Semi-structured, Diverse |
Query Language | Standardized SQL | Varied, Database-Specific APIs/Languages |
Transaction Support | Strong, Multi-Statement ACID | Varies (Often single-record atomic, some full ACID) |
Key Strength | Data Integrity, Complex Queries, Standardization | Flexibility, Scalability, Performance (specific use cases) |
B. Khi nào Chọn Loại nào
Quyết định phụ thuộc vào các yêu cầu cụ thể của ứng dụng:
Chọn SQL (Quan hệ) khi:
- Cần sự An toàn Tuyệt đối (Tuân thủ ACID):
Ví dụ: Hệ thống ngân hàng (chuyển tiền phải chính xác tuyệt đối), quản lý kho hàng (số lượng tồn kho phải đúng), các ứng dụng yêu cầu tuân thủ quy định nghiêm ngặt về dữ liệu.
Tại sao? SQL với ACID đảm bảo mọi giao dịch diễn ra một cách toàn vẹn (hoặc thành công hết, hoặc thất bại hết, không có trạng thái lưng chừng), dữ liệu luôn nhất quán và chính xác.
- Cấu trúc Dữ liệu Ổn định và Rõ ràng:
Ví dụ: Thông tin nhân viên trong công ty, danh mục sản phẩm với các thuộc tính cố định, dữ liệu kế toán.
Tại sao? Cấu trúc bảng, cột của SQL rất phù hợp để mô hình hóa những dữ liệu này. Bạn biết rõ mình cần lưu gì và mối quan hệ giữa chúng không thay đổi đột ngột.
- Thực hiện truy vấn Phức tạp:
Ví dụ: Phân tích doanh thu theo nhiều tiêu chí (kết hợp dữ liệu từ bảng khách hàng, đơn hàng, sản phẩm), tạo báo cáo tổng hợp phức tạp.
Tại sao? Ngôn ngữ SQL cực kỳ mạnh mẽ cho việc truy vấn, kết hợp (JOIN), lọc, và tổng hợp dữ liệu từ nhiều bảng khác nhau.
Chọn NoSQL khi:
Xử lý Dữ liệu Khổng lồ và Đa dạng:
Ví dụ: Lưu trữ hàng tỷ bài đăng trên mạng xã hội, dữ liệu từ cảm biến IoT (nhiệt độ, độ ẩm...), log hệ thống, file ảnh, video.
Tại sao? NoSQL thường xử lý tốt hơn với dữ liệu không có cấu trúc rõ ràng hoặc cấu trúc thay đổi liên tục, và có khả năng lưu trữ lượng dữ liệu cực lớn.
Ưu tiên Tốc độ Cực Nhanh (Độ trễ thấp) và Lưu lượng Cao:
Ví dụ: Các ứng dụng cần phản hồi tức thì như quảng cáo thời gian thực, game online, cache dữ liệu cho website đông người truy cập.
Tại sao? Các mô hình dữ liệu đơn giản hơn (như Key-Value) và kiến trúc phân tán của NoSQL thường cho phép tốc độ đọc/ghi nhanh hơn cho các tác vụ đơn giản.
Cần Schema Linh hoạt, Hay Thay đổi:
Ví dụ: Danh mục sản phẩm thương mại điện tử nơi mỗi loại sản phẩm có thể có bộ thông số kỹ thuật riêng, các dự án phát triển nhanh cần thay đổi cấu trúc dữ liệu liên tục mà không muốn gián đoạn.
Tại sao? Sự linh hoạt của NoSQL giúp bạn dễ dàng thêm/bớt thuộc tính mà không cần định nghĩa lại toàn bộ cấu trúc, tăng tốc độ phát triển.
Khả năng Mở rộng Ngang là Yếu tố Sống còn:
Ví dụ: Các ứng dụng dự kiến có lượng người dùng hoặc dữ liệu tăng trưởng theo cấp số nhân (mạng xã hội, nền tảng SaaS...).
Tại sao? NoSQL được thiết kế để dễ dàng "thêm máy chủ" khi cần, giúp hệ thống đáp ứng được tải ngày càng tăng.
C. Cân nhắc về Hiệu suất: B-Trees vs. LSM-Trees
Cấu trúc dữ liệu cơ bản được sử dụng bởi storage engine
của database
ảnh hưởng đáng kể đến đặc điểm hiệu suất đọc và ghi của nó. Hai cấu trúc phổ biến là B-Trees
(và các biến thể như B+ Trees
) và Log-Structured Merge Trees
(LSM-Trees
).
- B-Trees (Phổ biến trong RDBMS):
Cấu trúc:
B-Trees
là cấu trúc cây cân bằng được tối ưu hóa cho việc tìm kiếm. Dữ liệu thường được lưu trữ theo thứ tự sắp xếp trong các trang lá (leaf pages
), cho phép tra cứu điểm (point lookups
) và quét phạm vi (range scans
) hiệu quả. Chúng là cấu trúcindex
tiêu chuẩn trong cácdatabase
nhưPostgreSQL
,MySQL
(InnoDB
), vàOracle
.Tưởng tượng một thư viện được sắp xếp cực kỳ khoa học bằng hệ thống thẻ mục lục (index) theo cây phân cấp (B-Tree). Mọi cuốn sách (dữ liệu) đều được đặt đúng vị trí theo thứ tự. Để tìm sách, bạn chỉ cần tra thẻ mục lục và đi thẳng đến kệ chứa nó.
Hiệu suất Đọc: Rất nhanh, đặc biệt nếu dữ liệu đã được tải vào bộ nhớ (cache) hoặc khi cần quét phạm vi (range scan) (như tìm tất cả sách có Mã sách từ 100 đến 200).
Hiệu suất Ghi: Chậm hơn khi ghi hoặc cập nhật, vì phải thay đổi dữ liệu trên đĩa. Quá trình điển hình là đọc-sửa-ghi (
read-modify-write
): tìm nạp trang liên quan từ đĩa vào bộ nhớ, sửa đổi nó, và ghi lại toàn bộ trang. Nếu trang đầy, B-Trees phải "chia trang" (page split), làm tăng chi phí. Bên cạnh đó, việc này có thể dẫn đến khuếch đại ghi (write amplification
) khi một thay đổi nhỏ (như sửa giá sách) có thể yêu cầu ghi lại toàn bộ trang (thường là 8KB), dù chỉ thay đổi vài byte.
- LSM-Trees (Phổ biến trong NoSQL được Tối ưu hóa Ghi):
Cấu trúc:
LSM-Trees
được thiết kế cho thông lượng ghi cao. Các ghi đến đầu tiên được đệm trong một cấu trúc trong bộ nhớ (thường được gọi làmemtable
, điển hình là một cấu trúc được sắp xếp nhưskip list
hoặc cây). Khimemtable
đầy, nó được đẩy (flushed
) xuống đĩa dưới dạng một tệp phân đoạn (segment
) bất biến, được sắp xếp (SSTable
). Việc đọc có thể phải kiểm tramemtable
và nhiềuSSTables
trên đĩa. Một quy trình nén (compaction
) chạy nền định kỳ hợp nhất cácSSTables
để loại bỏ dữ liệu đã xóa/cập nhật và hợp nhất các tệp, cải thiện hiệu quả đọc.Tưởng tượng một bàn lễ tân rất bận. Thư mới (dữ liệu ghi mới) đến được bỏ tạm vào một cái khay "Thư mới đến" rất nhanh (memtable trong bộ nhớ). Khi khay đầy, nhân viên sẽ gom cả lô thư đó, sắp xếp nhanh, đóng vào một thùng dán nhãn ngày tháng (SSTable) và cất vào kho lưu trữ trên đĩa. Họ không cố gắng nhét từng lá thư vào các thùng cũ. Định kỳ, họ sẽ vào kho, gom các thùng cũ lại, loại bỏ thư rác/thư trùng, sắp xếp lại cho gọn (compaction).
Hiệu suất Đọc: Việc đọc có thể chậm hơn
B-Trees
vì dữ liệu có thể tồn tại trongmemtable
hoặc nhiềuSSTables
.Databases
thường sử dụng bộ lọc Bloom (Bloom filters
)—cấu trúc dữ liệu xác suất—để nhanh chóng xác định xem mộtSSTable
có thể chứa khóa hay không, tránh các lần đọc đĩa không cần thiết. Tuy nhiên, một lần đọc logic duy nhất vẫn có thể yêu cầu nhiều lần tìm kiếm/đọc đĩa trong trường hợp xấu nhất, dẫn đến khuếch đại đọc (read amplification
) cao hơn.Nhiều CSDL NoSQL tối ưu cho việc ghi nhiều như Cassandra, HBase, LevelDB, RocksDB (thường dùng trong các hệ thống ghi log, dữ liệu chuỗi thời gian...).
Hiệu suất Ghi:
LSM-Trees
cung cấp hiệu suất ghi cao, vì các thao tác ghi chủ yếu là thêm (append
) vàomemtable
trong bộ nhớ, sau đó là đẩy (flush
) tuần tự cácSSTables
xuống đĩa. Điều này tránh được I/O ngẫu nhiên và chi phí đọc-sửa-ghi củaB-Trees
. Khuếch đại ghi (write amplification
) vẫn xảy ra, nhưng nó xảy ra trong quá trìnhcompaction
nền thay vì trên đường dẫn ghi tiền cảnh. Tùy thuộc vào chiến lượccompaction
(ví dụ:leveled
vs.tiered
), tổngwrite amplification
thường có thể thấp hơn so vớiB-Trees
dưới tải ghi nặng.LSM-Trees
cũng có thể hấp thụ tốt hơn các đợt ghi bùng nổ tạm thời bằng cách đệm trong bộ nhớ.
Sự lựa chọn giữa các storage engines
dựa trên B-Tree
và LSM-Tree
phản ánh một sự đánh đổi hiệu suất cơ bản. B-Trees
thường cung cấp hiệu suất đọc tốt hơn và dễ dự đoán hơn, đặc biệt là đối với range scans
, làm cho chúng phù hợp với khối lượng công việc RDBMS
truyền thống thường thiên về đọc hoặc cân bằng. LSM-Trees
xuất sắc về thông lượng ghi, làm cho chúng trở thành lựa chọn phổ biến cho các ứng dụng ghi nhiều thường thấy trong không gian NoSQL
, chẳng hạn như hệ thống logging
, time-series databases
, hoặc các hệ thống như Apache Cassandra
. Sự khác biệt này trong chiến lược lưu trữ cơ bản là một lý do kỹ thuật chính đằng sau các hồ sơ hiệu suất khác nhau thường được quan sát giữa SQL
và một số NoSQL databases
nhất định.
V. Mở rộng Quy mô Databases cho Tăng trưởng
Khi các ứng dụng thành công, chúng chắc chắn phải đối mặt với khối lượng dữ liệu và lưu lượng truy cập người dùng ngày càng tăng. Việc mở rộng quy mô lớp database
để xử lý sự tăng trưởng này là một thách thức quan trọng, liên quan đến các kỹ thuật như replication
và partitioning
/sharding
.
A. Những Thách thức của việc Mở rộng SQL theo Chiều ngang: Việc mở rộng quy mô SQL databases
truyền thống theo chiều ngang (trên nhiều máy chủ) có nhiều khó khăn:
Duy trì
ACID
trên các Nodes: Đảm bảo các thuộc tínhACID
, đặc biệt làAtomicity
vàConsistency
, trên cáctransactions
kéo dài trên nhiều máy chủdatabase
độc lập (shards
) vốn đã phức tạp. Các hoạt động như chuyển khoản ngân hàng liên quan đến các tài khoản trên cácshards
khác nhau yêu cầu các giao thứctransaction
phân tán (ví dụ:Two-Phase Commit
-2PC
). Các giao thức này gây ra độ trễ và chi phí giao tiếp đáng kể, và chúng dễ bị lỗi – nếu mộtnode
tham gia vàotransaction
bịcrash
, toàn bộtransaction
có thể bị chặn hoặc yêu cầu các quy trình phục hồi phức tạp. Việc đạt đượclatency
thấp vàhigh availability
trong khi đảm bảodurability
vàatomicity
trong cáctransactions
phân tán là một trở ngại lớn.Thực thi
JOINs
Phân tán: Thực hiện các phép toánJOIN
trên dữ liệu được phân phối trên cácshards
khác nhau tốn kém về mặt tính toán và đòi hỏi nhiều tài nguyên mạng. Nó yêu cầu tìm nạp dữ liệu từ nhiều máy chủ, chuyển một lượng lớn dữ liệu qua mạng, và sau đó thực hiện logicjoin
, ảnh hưởng đáng kể đến hiệu suất truy vấn.Độ phức tạp Vận hành: Việc quản lý một
cluster
cácSQL databases
đượcreplicated
và/hoặcsharded
liên quan đến chi phí vận hành đáng kể cho việc cấu hình, giám sát, sao lưu, nâng cấp và thay đổischema
so với việc quản lý mộtinstance
duy nhất.
Những thách thức này giải thích tại sao các SQL databases
truyền thống thường phụ thuộc nhiều vào vertical scaling
và tại sao việc đạt được horizontal scaling
thường yêu cầu các distributed SQL databases
chuyên biệt hoặc thiết kế cẩn thận ở cấp ứng dụng.
B. Sao chép (Replication
): Tăng cường Tính Sẵn sàng và Khả năng Mở rộng Đọc Replication
liên quan đến việc tạo và duy trì nhiều bản sao (replicas
) của một database
trên các máy chủ khác nhau. Mục tiêu chính của nó là cải thiện availability
dữ liệu bằng cách loại bỏ các điểm lỗi duy nhất (Single Points of Failure
- SPOF
) và tăng cường hiệu suất đọc bằng cách phân phối các truy vấn đọc trên nhiều replicas
. Nếu một máy chủ database
bị lỗi, một replica
có thể tiếp quản hoặc tiếp tục phục vụ các yêu cầu. Lưu lượng đọc cao có thể được cân bằng trên nhiều replicas
.
Hãy nghĩ về nó giống như có nhiều giao dịch viên ngân hàng mở thay vì chỉ một; khối lượng công việc được phân phối, và dịch vụ vẫn tiếp tục ngay cả khi một giao dịch viên nghỉ giải lao. Hoặc, xem xét physical replication
như sao chép toàn bộ ổ cứng so với logical replication
như sao chép các tệp cụ thể – một đảm bảo khớp từng byte, trong khi cái kia tập trung vào các thay đổi logic.
Một số mô hình replication
tồn tại, mỗi mô hình có những đánh đổi khác nhau về consistency
, availability
, và độ phức tạp:
Sao chép Đơn Lãnh đạo (
Single-Leader
-Master-Slave
):Cơ chế: Một máy chủ được chỉ định,
leader
(hoặcmaster
), xử lý tất cả các hoạt động ghi (writes
). Cácwrites
này sau đó được lan truyền (replicated
) đến một hoặc nhiều máy chủfollower
(hoặcslave
). Các truy vấn đọc có thể được chuyển đếnmaster
hoặc bất kỳslave
nào.Ưu điểm: Mô hình
consistency
tương đối đơn giản, vì tất cả cácwrites
đều đi qua một điểm sắp xếp duy nhất. Tuyệt vời để mở rộng quy mô khối lượng công việc thiên về đọc bằng cách thêm nhiềureplicas
hơn.Nhược điểm:
Master
đại diện cho mộtSPOF
tiềm năng; nếu nó bị lỗi, cần có quy trình chuyển đổi dự phòng (failover
) để nâng cấp mộtfollower
trở thànhmaster
mới. Thông lượng ghi bị giới hạn bởi dung lượng củamaster
duy nhất. Có thể có độ trễ sao chép (replication lag
), nơi cácfollowers
hơi chậm hơnmaster
, có nghĩa là các lần đọc từfollowers
có thể trả về dữ liệu cũ (eventual consistency
cho các lần đọc từfollowers
).
Sao chép Đa Lãnh đạo (
Multi-Leader
-Master-Master
):Cơ chế: Nhiều máy chủ được chỉ định làm
leaders
, và mỗi máy chủ có thể chấp nhận các hoạt động ghi. Cácwrites
được chấp nhận bởi mộtleader
đượcreplicated
đến cácleaders
khác và bất kỳfollowers
liên quan nào.Ưu điểm: Cải thiện
availability
ghi – nếu mộtleader
bị lỗi, nhữngleader
khác vẫn có thể chấp nhậnwrites
. Có thể giảmlatency
ghi cho các ứng dụng phân tán về mặt địa lý, vì người dùng có thể ghi vào mộtleader
gần đó [Ghi chú của người dùng].Nhược điểm: Thách thức chính là giải quyết xung đột ghi (
write conflict resolution
). Nếu cùng một dữ liệu được sửa đổi đồng thời trên cácleaders
khác nhau, hệ thống cần một chiến lược để xác địnhwrite
nào "thắng" (ví dụ: dựa trên dấu thời gian, quy tắc cụ thể, hoặc can thiệp thủ công). Điều này làm phức tạp đáng kể các đảm bảoconsistency
.
Sao chép Không Lãnh đạo (
Leaderless
- ví dụ: kiểu Dynamo):Cơ chế: Không có
leaders
được chỉ định; bất kỳnode
replica
nào cũng có thể chấp nhận yêu cầu ghi. Khi một client ghi dữ liệu, nó thường gửiwrite
đến nhiềureplicas
đồng thời. Việc đọc cũng có thể truy vấn nhiềureplicas
để tìm phiên bản gần đây nhất hoặc đảm bảoconsistency
. Thường sử dụngquorums
cho đọc (R) và ghi (W): mộtwrite
được coi là thành công nếu được xác nhận bởi Wnodes
, và một lần đọc là thành công nếu Rnodes
phản hồi. Cấu hình W + R > N (tổng sốreplicas
) thường cung cấp đảm bảostrong consistency
, trong khi các giá trị thấp hơn ưu tiênavailability
.Ưu điểm:
High availability
cho cả đọc và ghi, vì lỗi của cácnodes
riêng lẻ không ngăn hệ thống xử lý yêu cầu (miễn là còn đủreplicas
). Khả năng chịu lỗi tuyệt vời.Nhược điểm: Các đảm bảo
consistency
có thể phức tạp để quản lý và lý giải, đặc biệt là với cácwrites
đồng thời dẫn đến các phiên bản dữ liệu có khả năng xung đột. Các cơ chế như sửa chữa khi đọc (read repair
- sửa lỗi không nhất quán trong quá trình đọc) hoặc logic giải quyết xung đột rõ ràng có thể cần thiết.Cassandra
, ví dụ, sử dụngquorums
có thể điều chỉnh để cân bằngconsistency
vàavailability
[Ghi chú của người dùng].
Sao chép Logic vs. Vật lý (
Logical vs. Physical Replication
):Replication
có thể xảy ra ở các cấp độ khác nhau.Physical replication
sao chép các thay đổi cấp thấp vào các tệpdatabase
(ví dụ: truyền các bản ghiWrite-Ahead Log
). Nó thường đơn giản hơn và đảm bảo một bản sao chính xác nhưng kém linh hoạt hơn.Logical replication
sao chép các hoạt động logic (ví dụ: câu lệnhSQL
hoặc các thay đổi cấprow
). Nó linh hoạt hơn, cho phépreplication
giữa các phiên bảndatabase
hoặc nền tảng khác nhau,replication
chọn lọc cáctables
/databases
, nhưng có thể có chi phí cao hơn.
Sự lựa chọn mô hình replication
ảnh hưởng cơ bản đến hành vi của hệ thống. Các mô hình single-leader
cung cấp quản lý consistency
đơn giản hơn nhưng giới hạn availability
ghi. Các mô hình multi-leader
và leaderless
ưu tiên availability
, đặc biệt là cho ghi, nhưng giới thiệu sự phức tạp đáng kể xung quanh việc quản lý các cập nhật đồng thời và đảm bảo consistency
dữ liệu trên các replicas
. Điều này phản ánh sự đánh đổi cố hữu giữa consistency
và availability
trong các hệ thống phân tán.
Bảng 2: So sánh các Mô hình Sao chép (Replication
)
Tính năng | Single-Leader (Master-Slave) | Multi-Leader (Master-Master) | Leaderless (e.g., Quorum-based) |
Write Path | To Master only | To any Master | To W replicas |
Read Path | Master or Slaves | Any Master or Slaves | From R replicas |
Typical Consistency | Strong (on Master), Eventual (on Slaves) | Eventual (complex conflict resolution) | Tunable (via W, R, N) |
Conflict Handling | Not applicable (single writer) | High complexity | Moderate to High complexity |
Write Availability | Lower (Master SPOF) | Higher | Highest |
Read Scalability | High (add slaves) | High | High |
Overall Complexity | Lower | Higher | High |
Export to Sheets
(Xuất ra Sheets)
C. Phân vùng và Sharding (Partitioning and Sharding
): Mở rộng Quy mô Ghi và Kích thước Tập dữ liệu Khi một tập dữ liệu trở nên quá lớn để vừa trên một máy chủ duy nhất, hoặc khi thông lượng ghi vượt quá dung lượng của một máy duy nhất (ngay cả với replication
cho đọc), partitioning
hoặc sharding
trở nên cần thiết. Các kỹ thuật này liên quan đến việc chia một database
lớn thành các phần nhỏ hơn, dễ quản lý hơn. Mặc dù đôi khi được sử dụng thay thế cho nhau, partitioning
có thể đề cập đến việc chia dữ liệu trong một máy chủ duy nhất, trong khi sharding
thường ám chỉ việc phân phối các phân vùng này trên nhiều máy chủ độc lập. Trọng tâm ở đây là sharding
để mở rộng theo chiều ngang.
Hãy tưởng tượng một thư viện khổng lồ; sharding
giống như chia bộ sưu tập thành các khu vực (ví dụ: Tiểu thuyết, Phi hư cấu, Khoa học) được đặt trong các phòng khác nhau hoặc thậm chí các tòa nhà khác nhau, làm cho mỗi khu vực dễ quản lý và tìm kiếm hơn. Hoặc, tại một bữa tiệc buffet lớn, sharding
giống như thiết lập các quầy riêng biệt cho món khai vị, món chính và món tráng miệng.
Có hai cách tiếp cận chính để chia dữ liệu [Ghi chú của người dùng]:
Phân vùng/Sharding Dọc (
Vertical Partitioning/Sharding
): Chia mộttable
dựa trên cáccolumns
của nó. Cáccolumns
thường được truy cập cùng nhau có thể được giữ trong một phân vùng, trong khi cáccolumns
lớn hoặc ít được sử dụng (nhưBLOBs
hoặc trường văn bản) được chuyển sang phân vùng khác.Ưu điểm: Có thể cải thiện hiệu suất truy vấn bằng cách giảm lượng dữ liệu đọc từ đĩa nếu truy vấn chỉ cần các
columns
từ một phân vùng.Nhược điểm: Không trực tiếp giải quyết việc mở rộng số lượng
rows
. Nếu cần dữ liệu từ nhiều phân vùng dọc, cần có các phépJOIN
tốn kém. Nó cũng có thể dẫn đến tải không đồng đều nếu một số phân vùng được truy cập thường xuyên hơn nhiều [Ghi chú của người dùng].
Phân vùng/Sharding Ngang (
Horizontal Partitioning/Sharding
): Chia mộttable
dựa trên cácrows
của nó.Table
được chia thành nhiềutables
nhỏ hơn (shards
), mỗishard
chứa một tập hợp con cácrows
nhưng duy trì cùng mộtschema
. Cácshards
này sau đó được phân phối trên các máy chủdatabase
khác nhau. Đây là kỹ thuật chính để mở rộng quy mô khối lượng dữ liệu và thông lượng ghi.
Một số chiến lược tồn tại để xác định cách phân phối rows
trên các shards
trong horizontal sharding
:
Sharding Dựa trên Phạm vi (
Range-Based Sharding
): Dữ liệu được phân vùng dựa trên một phạm vi giá trị liên tục trong mộtcolumn
cụ thể, được gọi là khóashard
(shard key
) (ví dụ: User IDs 1-1000 trên Shard A, 1001-2000 trên Shard B, Zip Codes 00000-49999 trên Shard C, 50000-99999 trên Shard D).Ưu điểm: Tương đối đơn giản để triển khai và hiểu. Hiệu quả cho các truy vấn yêu cầu dữ liệu trong một phạm vi cụ thể của
shard key
.Nhược điểm: Dễ bị
hotspots
– phân phối dữ liệu hoặc tải không đồng đều. Ví dụ, nếushard key
là dấu thời gian, tất cả dữ liệu mới có thể đổ vàoshard
mới nhất, làm quá tải nó. Tương tự, nếu phân phối dữ liệu bị lệch (ví dụ: nhiều khách hàng hơn trong các phạm vi mã zip nhất định), cácshards
đó sẽ chịu tải không cân xứng. Việc quản lý phạm vi và chiashards
có thể yêu cầu can thiệp thủ công.
Sharding Dựa trên Băm (
Hash-Based Sharding
): Một hàm băm (hash function
) được áp dụng choshard key
, và giá trị băm kết quả xác địnhshard
mà dữ liệu thuộc về. Một cách tiếp cận đơn giản phổ biến làshard_id = hash(shard_key) % number_of_shards
.Ưu điểm: Thường dẫn đến phân phối dữ liệu đồng đều hơn trên các
shards
, giảm thiểu vấn đềhotspot
phổ biến trongrange-based sharding
.Nhược điểm: Làm cho các truy vấn phạm vi trên
shard key
rất kém hiệu quả, vì các giá trị khóa liên tiếp bị phân tán ngẫu nhiên trên cácshards
. Một nhược điểm đáng kể là độ phức tạp của việc băm lại (rehashing
): việc thêm hoặc xóashards
làm thay đổi kết quả của phép toán modulo, thường yêu cầu phân phối lại hàng loạt dữ liệu hiện có trên hầu hết tất cả cácshards
[Ghi chú của người dùng].
Sharding Dựa trên Thư mục (
Directory-Based Sharding
): Một dịch vụ tra cứu hoặctable
riêng biệt (thư mục -directory
) duy trì ánh xạ giữa cácshard keys
(hoặc phạm vi khóa) và vị tríshard
vật lý nơi dữ liệu tương ứng cư trú. Để định vị dữ liệu, ứng dụng trước tiên truy vấn thư mục để tìmshard
chính xác, sau đó truy vấnshard
đó.Ưu điểm: Cung cấp sự linh hoạt tối đa trong phân phối dữ liệu. Các
shards
có thể được chia hoặc hợp nhất, và dữ liệu có thể được di chuyển đơn giản bằng cách cập nhật ánh xạ thư mục, mà không cầnrehashing
phức tạp. Cho phép kiểm soát chi tiết về vị trí dữ liệu.Nhược điểm: Bản thân thư mục có thể trở thành nút thắt hiệu suất (yêu cầu một bước tra cứu bổ sung) và một điểm lỗi duy nhất nếu không được làm cho có
high availability
. Thêm độ phức tạp vận hành để duy trì thư mục.
Băm Nhất quán (
Consistent Hashing
- Giải quyết Vấn đề Băm lại của Hash-Based): Đây không phải là một chiến lượcsharding
riêng biệt mà là một kỹ thuật băm tiên tiến thường được sử dụng tronghash-based sharding
để khắc phục vấn đềrehashing
tốn kém khi số lượngshards
thay đổi.Cơ chế: Nó ánh xạ cả máy chủ (
shards
) và khóa dữ liệu lên một vòng tròn trừu tượng (một vòng băm -hash ring
, thường đại diện cho một không gian giá trị băm lớn, ví dụ: 0 đến 232−1). Một khóa được gán cho máy chủ đầu tiên gặp phải khi di chuyển theo chiều kim đồng hồ xung quanh vòng từ vị trí của khóa.Lợi ích: Khi một máy chủ được thêm hoặc xóa, chỉ các khóa ánh xạ tới phạm vi ngay liền kề với máy chủ đó trên vòng mới cần được phân phối lại. Trung bình, việc thêm hoặc xóa một máy chủ chỉ yêu cầu di chuyển một phần (k/n, trong đó k là số lượng khóa và n là số lượng máy chủ) của các khóa, giảm đáng kể nỗ lực cân bằng lại so với băm modulo đơn giản.
Giảm thiểu Hotspot: Mặc dù tốt hơn băm modulo,
consistent hashing
cơ bản vẫn có thể dẫn đến tải không đồng đều nếu các máy chủ tình cờ rơi vào các vị trí không đều trên vòng. Điều này thường được giải quyết bằng cách sử dụng các nút ảo (virtual nodes
hoặcvnodes
), trong đó mỗi máy chủ vật lý được gán nhiều vị trí (virtual nodes
) trênhash ring
, dẫn đến phân phối khóa mượt mà và cân bằng hơn nhiều.
Chọn Khóa Shard (
Shard Key
): Việc lựa chọnshard key
là rất quan trọng cho sự thành công củahorizontal sharding
. Mộtshard key
lý tưởng nên cócardinality
cao (nhiều giá trị duy nhất) và phân phối dữ liệu và tải truy vấn đồng đều trên cácshards
. Nó cũng nên phù hợp với các mẫu truy vấn phổ biến để giảm thiểu nhu cầu về các truy vấn chéoshard
(cross-shard queries
), vốn phức tạp và chậm.
Thách thức: Sharding
giới thiệu sự phức tạp đáng kể vượt ra ngoài một database
đơn máy chủ. Các thách thức chính bao gồm xử lý các transactions
kéo dài trên nhiều shards
, thực hiện joins
trên các shards
, cân bằng lại dữ liệu một cách hiệu quả khi các shards
được thêm hoặc xóa (ngay cả với consistent hashing
, vẫn cần di chuyển một số dữ liệu), và gánh nặng vận hành tổng thể tăng lên khi quản lý một cluster
phân tán.
Bảng 3: So sánh các Chiến lược Sharding Ngang
Feature | Range-Based | Hash-Based (Modulo) | Hash-Based (Consistent Hashing) | Directory-Based |
Mechanism | Key range assignment | hash(key) % N | Map key/server to hash ring | Lookup table maps key to shard |
Data Distribution | Potentially uneven (skewed) | Generally even | Generally even (esp. w/ vnodes) | Highly flexible |
Range Query (on Key) | Efficient | Inefficient | Inefficient | Depends on directory structure |
Hotspot Potential | High | Low | Low (esp. w/ vnodes) | Low (if directory managed well) |
Rebalancing Effort | Moderate (split/merge ranges) | Very High (most keys move) | Low (only adjacent keys move) | Low (update directory) |
Key Benefit | Simple, good for range queries | Even distribution | Minimal rebalancing disruption | Maximum flexibility |
Export to Sheets
(Xuất ra Sheets)
D. Khi nào Nên Shard (và Khi nào Không) Sharding
là một kỹ thuật mạnh mẽ, nhưng nó làm tăng thêm độ phức tạp. Quyết định shard
nên được cân nhắc kỹ lưỡng:
Cân nhắc một Database Tập trung (Không Sharding) khi: [Ghi chú của người dùng]
Đảm bảo
ACID
mạnh mẽ trên toàn bộ tập dữ liệu là tối quan trọng và dễ dàng quản lý trên mộtnode
duy nhất.Yêu cầu kinh doanh và mô hình dữ liệu tương đối ổn định.
Kích thước tập dữ liệu và tải lưu lượng truy cập dự kiến có thể được xử lý thoải mái bởi một máy chủ được
vertically scaled
duy nhất (có thể là một máy chủ rất lớn). Việcsharding
sớm có thể thêm độ phức tạp không cần thiết.
Cân nhắc một Database Phân tán (Sharding) khi:
Khối lượng dữ liệu vượt quá dung lượng lưu trữ của máy chủ đơn lẻ thực tế lớn nhất.
Yêu cầu thông lượng ghi vượt quá dung lượng của một
master
duy nhất (ngay cả vớireplication
).Đọc/ghi có độ trễ thấp là rất quan trọng và có thể đạt được bằng cách phân phối dữ liệu gần người dùng hơn hoặc xử lý các truy vấn song song trên các
shards
.High availability
là rất quan trọng, và khả năng hệ thống hoạt động ngay cả khi một sốshards
bị lỗi (chỉ ảnh hưởng đến một tập hợp con dữ liệu) là mong muốn.
VI. Kết luận: Điều hướng các Lựa chọn và Đánh đổi Database Bối cảnh lưu trữ và quản lý dữ liệu trải dài từ các phương pháp dựa trên tệp đơn giản đến các hệ thống database
phân tán rất tinh vi. Hành trình này bao gồm việc hiểu thế giới có cấu trúc của relational databases
(SQL
) với các đảm bảo ACID
mạnh mẽ của chúng, khám phá lĩnh vực đa dạng và linh hoạt của NoSQL databases
được tối ưu hóa cho các mô hình dữ liệu và mẫu scalability
khác nhau, và đi sâu vào các kỹ thuật được sử dụng để mở rộng quy mô hệ thống, chẳng hạn như replication
và sharding
. Hiệu suất cơ bản bị ảnh hưởng nặng nề bởi các cấu trúc bên trong như B-Trees
và LSM-Trees
.
Trong suốt quá trình khám phá này, một chủ đề trung tâm nổi lên: thiết kế hệ thống database
về cơ bản là một bài tập quản lý sự đánh đổi. Hiếm khi có một giải pháp "tốt nhất" duy nhất; thay vào đó, các lựa chọn liên quan đến việc cân bằng các yêu cầu cạnh tranh:
Nhất quán vs. Sẵn sàng (
Consistency vs. Availability
): Định lýCAP
nhấn mạnh khó khăn của việc đồng thời đảm bảostrong consistency
,high availability
, và khả năng chịu lỗinetwork partitions
trong các hệ thống phân tán. Thông thường, các hệ thống phải chọn hai trong ba yếu tố để ưu tiên trong quá trình phân vùng, dẫn đến những đánh đổi nhưACID
vs.BASE
.Nhất quán vs. Hiệu suất/Khả năng mở rộng (
Consistency vs. Performance/Scalability
): Việc thực thistrong consistency
, đặc biệt là trên cácnodes
phân tán, thường gây ra độ trễ và chi phí, có khả năng hạn chếperformance
vàscalability
so với các hệ thống cung cấp các mô hìnhconsistency
thoải mái hơn.Hiệu suất Đọc vs. Hiệu suất Ghi (
Read Performance vs. Write Performance
): Cácstorage engines
cơ bản nhưB-Trees
(thường đọc tốt hơn) vàLSM-Trees
(thường ghi tốt hơn) thể hiện sự đánh đổi này, ảnh hưởng đến sự phù hợp củadatabases
cho các mẫu khối lượng công việc khác nhau.Linh hoạt Schema vs. Toàn vẹn Dữ liệu (
Schema Flexibility vs. Data Integrity
): Cácschema
linh hoạt (NoSQL
) cho phép phát triển nhanh chóng nhưng có thể yêu cầu xác thực ở cấp ứng dụng nhiều hơn để đảm bảodata integrity
so với cácschema
cứng nhắc và các ràng buộc được thực thi bởiRDBMS
.Đơn giản Phát triển vs. Khả năng mở rộng/Hiệu suất (
Development Simplicity vs. Scalability/Performance
): MộtRDBMS
đơnnode
, đơn giản thường dễ phát triển hơn ban đầu, nhưng việc đạt được quy mô lớn có thể đòi hỏi thêm độ phức tạp về kiến trúc và vận hành của các hệ thốngNoSQL
hoặcdistributed SQL
(replication
,sharding
).Chuẩn hóa vs. Phi chuẩn hóa (
Normalization vs. Denormalization
):RDBMS
thường chuẩn hóa (normalize
) dữ liệu để giảm dư thừa và cải thiệnconsistency
, có khả năng phải trả giá bằng hiệu suất đọc (yêu cầujoins
).NoSQL
thường sử dụng phi chuẩn hóa (denormalization
) để cải thiện hiệu suất đọc bằng cách đặt dữ liệu liên quan gần nhau, với chi phí là sự dư thừa và các cập nhật có khả năng phức tạp hơn.
Với những phức tạp này, một số khuyến nghị cấp cao xuất hiện:
Bắt đầu Đơn giản: Trừ khi có các yêu cầu rõ ràng về quy mô lớn hoặc tính linh hoạt cực cao ngay từ đầu, hãy bắt đầu với kiến trúc đơn giản nhất đáp ứng nhu cầu hiện tại (thường là một
RDBMS
đơnnode
). Tránh tối ưu hóa sớm và sự phức tạp không cần thiết.Hiểu Rõ Yêu cầu: Trước khi chọn bất kỳ công nghệ
database
nào, hãy phân tích kỹ lưỡng các nhu cầu cụ thể của ứng dụng liên quan đến cấu trúc dữ liệu (structured
,semi-structured
,unstructured
), mẫu truy vấn (tỷ lệ đọc vs. ghi, độ phức tạp truy vấn, yêu cầulatency
), đảm bảoconsistency
(ACID
vs.eventual
), và quy mô dự kiến (khối lượng dữ liệu, tăng trưởng lưu lượng truy cập).Chọn Phù hợp trong các Danh mục: Nếu chọn
NoSQL
, hãy nhận biết sự đa dạng của nó. Chọn loạiNoSQL database
(Key-Value
,Document
,Wide-Column
,Graph
) phù hợp nhất với mô hình dữ liệu và mẫu truy cập của ứng dụng.Thừa nhận Độ phức tạp Vận hành: Việc triển khai và quản lý các hệ thống
database
phân tán (sử dụngreplication
và/hoặcsharding
) giới thiệu những thách thức vận hành đáng kể so với các hệ thống đơnnode
. Đảm bảo nhóm có chuyên môn và công cụ cần thiết.Giám sát và Lặp lại: Nhu cầu về hiệu suất và
scaling
database
luôn thay đổi. Liên tục giám sát hiệu suất hệ thống, xác định các nút thắt cổ chai, và chuẩn bị tối ưu hóa cấu hình, truy vấn,indexing
, hoặc thậm chí xem xét lại các lựa chọn kiến trúc dựa trên các mẫu sử dụng thực tế.
Cuối cùng, việc thiết kế các hệ thống database
hiệu quả đòi hỏi một cái nhìn tổng thể. Nó vượt ra ngoài việc chỉ đơn giản là so sánh danh sách tính năng của các sản phẩm khác nhau. Nó đòi hỏi sự hiểu biết về các nguyên tắc cơ bản—tính toàn vẹn giao dịch (ACID
), các ràng buộc hệ thống phân tán (CAP
), cấu trúc dữ liệu (B-Trees
, LSM-Trees
), và các kỹ thuật scaling
(replication
, sharding
)—và áp dụng kiến thức này một cách chiến lược. Mục tiêu là lựa chọn và cấu hình các công nghệ đáp ứng tốt nhất các mục tiêu cụ thể của ứng dụng trong khi quản lý một cách có ý thức các đánh đổi cố hữu ở mọi lớp của hệ thống.
Subscribe to my newsletter
Read articles from Ha Ngoc Hieu directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
