← Về danh sách
Cơ sở dữ liệu
#샤딩#수평분할#확장성#파티셔닝#127회
Cập nhật lần cuối · 2026-09-13

Phân mảnh cơ sở dữ liệu (Sharding)

1. Tổng quan

A. Định nghĩa

Sharding (phân mảnh) là kỹ thuật phân tán dữ liệu, phân chia ngang (Horizontal Partitioning) dữ liệu khối lượng lớn và lưu trữ vào nhiều cơ sở dữ liệu độc lập (shard), nhờ đó phân tán tải lưu trữ·xử lý của một cơ sở dữ liệu đơn lẻ sang nhiều máy chủ và bảo đảm khả năng mở rộng tuyến tính (Scale-out).

Ý tưởng cốt lõi của sharding là 'dữ liệu mà một DB không gánh nổi thì chia ra chứa ở nhiều máy'. Khi dịch vụ tăng trưởng và dữ liệu cùng lưu lượng bùng nổ, một máy chủ cơ sở dữ liệu sẽ đồng thời chạm giới hạn ở nhiều tài nguyên như dung lượng lưu trữ, CPU, bộ nhớ, I/O đĩa, số kết nối. Khi đó, mở rộng theo chiều dọc (Scale-up) — nâng cấu hình máy chủ — tuy đơn giản lúc đầu, nhưng có giới hạn căn bản: phần cứng cấu hình càng cao thì giá càng tăng theo cấp số nhân, có trần vật lý rõ ràng (số lõi·bộ nhớ mà một máy chủ có thể có), và rốt cuộc vẫn còn điểm lỗi đơn (SPOF).

Sharding vượt qua giới hạn này bằng mở rộng theo chiều ngang (Scale-out). Vì dữ liệu được chia theo đơn vị hàng (Row) và lưu rải trên nhiều máy chủ, có thể liên tục thêm máy chủ giá rẻ để tăng dung lượng và thông lượng gần như tuyến tính. Ví dụ, nếu chia dữ liệu người dùng theo ID người dùng, lưu 11 triệu ở shard 1, 1 triệu2 triệu ở shard 2, thì mỗi shard chỉ đảm nhận một phần của toàn bộ nên tải riêng lẻ giảm, và càng gắn thêm máy chủ thì tổng thông lượng càng lớn. Dữ liệu nào nằm ở shard nào được quyết định bởi khóa shard (Shard Key) và quy tắc định tuyến tương ứng.

Tuy nhiên lợi ích này có cái giá của nó. Vì dữ liệu phân tán về mặt vật lý nên truy vấn·join·tổng hợp trải trên nhiều shard trở nên khó khăn; nếu một giao dịch trải trên nhiều shard thì việc bảo đảm tính nguyên tử trở nên phức tạp; và khi thêm shard, gánh nặng phân phối lại dữ liệu (rebalancing) và quản lý vận hành tăng lên. Do đó, bài học thực tế là sharding là lá bài mở rộng cuối cùng được đưa vào 'khi một DB đơn lẻ không còn gánh nổi', và áp dụng sớm một cách thiếu cân nhắc chỉ làm tăng thêm độ phức tạp.

B. Bối cảnh xuất hiện và sự cần thiết

Sharding phát triển mạnh khi dịch vụ web trở nên phổ biến và dữ liệu người dùng·nội dung vượt mức terabyte. Các dịch vụ lớn thời kỳ đầu (tư tưởng Google Bigtable, MySQL sharding của Facebook, PostgreSQL sharding của Instagram, v.v.) đã sharding DB quan hệ ở tầng ứng dụng để gánh lưu lượng bùng nổ. Ngày nay mẫu này đã được hấp thụ thành chức năng tích hợp sẵn trong NoSQL·NewSQL·DB được quản lý trên đám mây, tiến hóa đến mức nhà phát triển có được khả năng mở rộng mà không phải tự hiện thực phân tán ở mức thấp.

2. Cấu trúc tổng thể của sharding

flowchart TB
  C["Client / ứng dụng"] --> R["Tầng định tuyến<br/>(khóa shard → ánh xạ shard)"]
  R --> S1[(Shard 1<br/>ID 1~1 triệu)]
  R --> S2[(Shard 2<br/>ID 1~2 triệu)]
  R --> S3[(Shard 3<br/>ID 2~3 triệu)]
  M["Metadata / thư mục<br/>(vị trí·trạng thái shard)"] -.-> R
  style R fill:#e8f0fe,stroke:#2f6fed,stroke-width:2px
  style M fill:#fef3e8,stroke:#ed8f2f

Hệ thống sharding về đại thể gồm ba tầng. Tầng định tuyến xem khóa shard trong yêu cầu để quyết định gửi đến shard nào. Kiến trúc thay đổi tùy việc đặt phần định tuyến này ở đâu: trong mã ứng dụng (phía client), ở proxy/middleware riêng (ví dụ: ProxySQL·Vitess cho MySQL, mongos của MongoDB), hay bên trong engine DB. Các shard là các instance DB độc lập với nhau (shared-nothing), mỗi shard tự xử lý trọn vẹn việc lưu trữ·truy vấn trên tập con dữ liệu của mình. Metadata/thư mục quản lý dải khóa nào nằm ở shard nào, trạng thái·vị trí bản sao của từng shard ra sao, làm căn cứ cho định tuyến.

Nguyên tắc thiết kế quan trọng ở đây là shared-nothing. Chỉ khi mỗi shard không chia sẻ tài nguyên và độc lập thì tải hay sự cố của một shard mới không lan sang shard khác, và mở rộng tuyến tính thực sự mới khả thi. Ngược lại, nếu các shard phụ thuộc vào kho lưu trữ chung hay khóa chung thì điểm đó trở thành nút thắt cổ chai mới và lợi ích của sharding biến mất.

Đặt tầng định tuyến ở đâu cũng quyết định tính chất của kiến trúc. Thứ nhất, định tuyến phía client để mã ứng dụng hoặc driver DB tự tính vị trí shard và kết nối trực tiếp tới shard đó. Không có bước trung gian nên độ trễ thấp, nhưng thay đổi topology shard phải được phản ánh trên mọi client nên mức gắn kết triển khai cao. Thứ hai, định tuyến bằng proxy/middleware (mongos, ProxySQL, VTGate của Vitess, v.v.) đặt một tầng chuyên định tuyến giữa ứng dụng và shard. Ứng dụng chỉ cần biết một endpoint duy nhất nên mức gắn kết giảm và việc resharding trở nên trong suốt, nhưng bản thân tầng proxy phải được dự phòng kép·mở rộng. Thứ ba, định tuyến tích hợp trong engine DB (như nút điều phối của Cassandra) cho phép kết nối vào nút nào thì yêu cầu cũng được chuyển đến đúng nút, nên vận hành đơn giản. Quy mô càng lớn thì càng có xu hướng chuyển từ phía client sang phương thức proxy·tích hợp trong engine.

3. Chiến lược phân chia (sharding) và định tuyến

flowchart LR
  K["Giá trị khóa shard"] --> A{"Chiến lược phân chia"}
  A -->|"Phạm vi"| RG["Range<br/>bố trí theo khoảng khóa"]
  A -->|"Băm"| HS["Hash<br/>hash(key) mod N"]
  A -->|"Thư mục"| DR["Directory<br/>tra bảng ánh xạ"]
  RG --> OUT["Xác định shard đích"]
  HS --> OUT
  DR --> OUT
  style A fill:#e8f0fe,stroke:#2f6fed,stroke-width:2px

Chiến lược phân chia xác định 'bố trí dữ liệu vào shard theo quy tắc nào', và mỗi chiến lược có ưu nhược điểm rõ rệt.

A. Sharding theo phạm vi (Range). Chia dữ liệu theo từng khoảng giá trị của khóa shard (ví dụ: ngày 2026-01 ở shard 1, 2026-02 ở shard 2). Ưu điểm là hiện thực trực quan, và truy vấn theo phạm vi (truy vấn một khoảng thời gian cụ thể) chỉ chạm tới ít shard nên hiệu quả. Tuy nhiên, với các dịch vụ chuỗi thời gian nơi thao tác ghi dồn vào dữ liệu gần nhất, dễ phát sinh điểm nóng (Hot Spot) khi lưu lượng tập trung vào 'shard cuối cùng'. Ví dụ, nếu sharding theo phạm vi dữ liệu log·đơn hàng theo thời điểm tạo, chỉ một shard mới nhất luôn bận rộn còn các shard khác nhàn rỗi, và hiệu quả phân tán sụp đổ.

B. Sharding theo băm (Hash). Đưa khóa shard vào hàm băm và dùng giá trị thu được để xác định shard (ví dụ: hash(user_id) mod N). Ưu điểm lớn nhất là phân bố khóa trở nên đồng đều nên dễ tránh điểm nóng. Ngược lại, vì các khóa liền kề bị rải sang các shard khác nhau nên truy vấn theo phạm vi bị phân tán ra mọi shard (scatter-gather), kém hiệu quả, và trên hết là khi số shard N thay đổi (mod N) thì nơi thuộc về của gần như toàn bộ dữ liệu thay đổi, gây ra phân phối lại quy mô lớn.

Để giảm nhẹ vấn đề phân phối lại bùng nổ này, băm nhất quán (Consistent Hashing) được sử dụng rộng rãi. Băm nhất quán bố trí khóa và nút trên một vòng băm (không gian tròn như 0~2³²−1), gán mỗi khóa cho nút gần nhất theo chiều kim đồng hồ. Khi thêm·xóa nút, chỉ dữ liệu ở đoạn liền kề di chuyển nên lượng tái bố trí được giới hạn ở mức trung bình K/N (tổng số khóa K, số nút N). Thêm vào đó, nếu rải một nút vật lý thành nhiều nút ảo (virtual node) trên vòng thì còn giảm được chênh lệch tải giữa các nút. Họ DynamoDB·Cassandra áp dụng nguyên lý này.

Nhìn bằng con số cụ thể thì khác biệt rất rõ. Khi có 4 nút, nếu dùng mod 4 đơn giản rồi tăng lên 5 nút thì về lý thuyết khoảng 80% tổng số khóa phải đổi shard sở hữu (tái bố trí bùng nổ). Ngược lại, với băm nhất quán, nút mới chỉ nhận một đoạn của vòng nên trung bình chỉ khoảng 1/5 (20%) tổng số di chuyển. Ở quy mô hàng trăm triệu bản ghi, khác biệt này trở thành yếu tố quyết định 'có thể mở rộng không gián đoạn hay không'.

Điểm nóng của sharding theo phạm vi thường được quan sát trong dịch vụ thực tế. Ví dụ, nếu sharding dữ liệu đơn hàng theo phạm vi order_id (tăng đơn điệu), đơn hàng mới luôn chỉ dồn vào shard cuối cùng, khiến IOPS ghi của riêng shard đó gần 100% còn các shard khác ở trạng thái rảnh. Để tránh điều này, thực tế người ta thiết kế lại khóa như gắn tiền tố băm ID người dùng thay cho khóa tuần tự, hoặc dùng chiến lược kết hợp: trục thời gian do partitioning đảm nhận, phân tán tải do hash sharding đảm nhận.

C. Sharding theo thư mục (Directory). Quản lý tường minh 'khóa nào nằm ở shard nào' trong một bảng tra cứu (thư mục) riêng. Vì có thể tự do thay đổi ánh xạ nên độ linh hoạt vận hành như phân phối lại·cô lập một khách hàng cụ thể là lớn nhất. Đổi lại, mọi truy vấn phải tra thư mục trước nên bắt buộc phải caching·dự phòng kép để bản thân thư mục không trở thành nút thắt·điểm lỗi đơn. Hữu ích trong SaaS cần bố trí chi tiết, như tách một khách hàng lớn (tenant) cụ thể sang shard riêng.

Ba chiến lược không loại trừ nhau mà còn được kết hợp. Tiêu biểu là các dịch vụ siêu lớn dùng cấu trúc 2 tầng 'ánh xạ shard logic (bucket ảo) sang shard vật lý bằng thư mục'. Trước hết băm khóa shard để đưa vào một trong hàng nghìn bucket logic cố định (phân tán đồng đều), còn việc máy chủ vật lý nào đảm nhận bucket đó được quản lý bằng thư mục. Khi đó, lúc tăng máy chủ vật lý chỉ cần chuyển 'bảng phân công bucket' chứ không phải dữ liệu, nên rebalancing trực tuyến dễ dàng hơn nhiều. Cách Instagram thời kỳ đầu đặt hàng nghìn shard logic trên PostgreSQL và ánh xạ vào số ít máy chủ vật lý là ví dụ nổi tiếng của mẫu này.

Chiến lược Ưu điểm Nhược điểm Ví dụ tiêu biểu
Phạm vi (Range) Truy vấn phạm vi hiệu quả, hiện thực đơn giản Dễ phát sinh điểm nóng HBase, MongoDB (range)
Băm (Hash) Phân tán đồng đều, giảm điểm nóng Truy vấn phạm vi kém hiệu quả, gánh nặng phân phối lại (→băm nhất quán) Cassandra, DynamoDB
Thư mục (Directory) Bố trí·phân phối lại linh hoạt Rủi ro nút thắt·SPOF ở thư mục Sharding tùy biến, một số SaaS

Chỉ bảng thôi thì chưa thấy rõ tiêu chí lựa chọn, nên bổ sung hàm ý thực tế. Mẫu truy vấn chủ đạo của dịch vụ chi phối việc chọn chiến lược. Workload truy vấn lặp lại dữ liệu của một người dùng cụ thể (ví dụ: 'dòng thời gian của tôi' trong dịch vụ mạng xã hội) có lợi với hash sharding theo ID người dùng, còn workload mà báo cáo theo khoảng thời gian là cốt lõi (ví dụ: phân tích log) có lợi với range sharding. Tức là lấy 'khóa được truy vấn thường xuyên nhất' làm khóa shard để thiết kế sao cho phần lớn truy vấn kết thúc trong một shard duy nhất là mấu chốt của hiệu năng.

4. Khác biệt giữa sharding với partitioning·replication

Sharding và partitioning giống nhau ở chỗ 'chia dữ liệu' nhưng khác nhau về phạm vi chia. Partitioning (phân vùng) là chia một bảng lớn thành nhiều phân vùng logic bên trong một máy chủ DB để cải thiện quản lý·hiệu năng, còn sharding là phân tán hẳn các mảnh đó sang nhiều máy chủ DB vật lý. Tức là có thể xem sharding là khái niệm mở rộng phân vùng ngang ra nhiều nút. Vì vậy partitioning không vượt qua được giới hạn tài nguyên của một máy chủ, còn sharding vượt qua chính giới hạn đó bằng cách tăng số máy chủ.

Một khái niệm khác cần phân biệt là nhân bản (Replication). Replication là sao chép y hệt cùng một dữ liệu lên nhiều máy chủ để có tính sẵn sàng và mở rộng đọc, còn sharding là chia chứa các dữ liệu khác nhau để mở rộng ghi·dung lượng. Hệ thống quy mô lớn thực tế kết hợp cả hai. Kiến trúc chuẩn mực là nhân bản lại từng shard (master-bản sao), vừa dùng sharding để tăng ghi·dung lượng, vừa dùng replication để bảo đảm tính sẵn sàng và hiệu năng đọc của từng shard.

Ví dụ, nếu mỗi shard trong 4 shard có 2 bản sao thì tổng cộng là 12 instance; khi đó ghi được mở rộng gấp 4 lần nhờ 4 master, đọc được phân tán trên 12 nút, và dù master nào hỏng thì bản sao được nâng cấp lên để duy trì tính sẵn sàng. Như vậy, tăng quy mô bằng tích 'sharding (mở rộng ghi) × replication (mở rộng đọc·tính sẵn sàng)' là bộ khung cơ bản của kiến trúc DB quy mô lớn hiện đại, và cũng phải cân nhắc rằng số instance cần quản lý và độ phức tạp vận hành cũng tăng theo cấp nhân tương ứng.

Tiêu chí Partitioning Sharding Replication
Dữ liệu Chia (trong cùng máy chủ) Chia (nhiều máy chủ) Sao chép (dữ liệu giống nhau)
Phân tán vật lý Không (một máy chủ) Có (nhiều máy chủ) Có (nhiều máy chủ)
Mục đích chính Quản lý·hiệu năng Mở rộng ghi·dung lượng Tính sẵn sàng·mở rộng đọc
Độ phức tạp Thấp Cao (định tuyến·giao dịch phân tán) Trung bình (trễ nhân bản·tính nhất quán)

5. Chuyên sâu — Vấn đề cross-shard và tự động hóa của DB được quản lý

Những vấn đề khó nhất gặp phải trong thực tế sau khi đưa sharding vào là phép toán xuyên shard (Cross-shard) và rebalancing.

Join·tổng hợp xuyên shard. Để join hoặc tổng hợp (COUNT, SUM, ORDER BY) dữ liệu nằm rải rác trên nhiều shard, tầng định tuyến phải rải truy vấn đến mọi shard liên quan (scatter) rồi thu thập và hợp nhất kết quả (gather). Với scatter-gather này, shard chậm nhất chi phối tổng thời gian phản hồi (độ trễ đuôi), và mức tiêu tốn tài nguyên tăng tỷ lệ với số shard. Vì vậy thực tế người ta giảm chính các phép toán xuyên shard bằng đồng vị trí dữ liệu (data colocation) — gom dữ liệu được truy vấn cùng nhau vào cùng shard (ví dụ: đặt một đơn hàng và chi tiết đơn hàng đó vào cùng shard theo order_id) — hoặc bằng thiết kế có view đã tổng hợp·phi chuẩn hóa trước dành riêng cho truy vấn.

Giao dịch phân tán. Nếu một giao dịch phải cập nhật nhiều shard thì cần giao dịch phân tán như cam kết 2 pha (2PC), nhưng điều này có nguy cơ lớn về suy giảm hiệu năng và sự cố bộ điều phối. Vì vậy nhiều hệ thống từ bỏ tính nguyên tử mạnh và chọn mô hình nhất quán cuối cùng như mẫu Saga, hoàn tác từng bước bằng giao dịch bù trừ. Đây là kết quả phản ánh vào thực tế đánh đổi của định lý CAP (dung hòa giữa tính nhất quán và tính sẵn sàng trong môi trường phân tán).

Rebalancing. Khi thêm shard, phải chuyển một phần dữ liệu sang shard mới, và việc di chuyển dữ liệu và cập nhật ánh xạ mà không gián đoạn dịch vụ (trực tuyến) là rất phức tạp. Người ta cục bộ hóa phạm vi di chuyển bằng băm nhất quán đã nói ở trên hoặc kỹ thuật ánh xạ shard logic (bucket ảo) sang shard vật lý (ví dụ: chunk của MongoDB, vindex của Vitess).

Tự động hóa của DB được quản lý·phân tán. Ngày nay phần lớn gánh nặng này được các sản phẩm hấp thụ. MongoDB tích hợp sẵn việc tự động chia chunk·balancer dựa trên khóa shard, Cassandra tự động phân phối lại khi thêm nút nhờ băm nhất quán. Vitess (do YouTube phát triển để mở rộng MySQL, đã tốt nghiệp CNCF) đặt sharding·định tuyến·resharding lên trên MySQL để giảm thiểu thay đổi ứng dụng. Các NewSQL như CockroachDB·Google Spanner cung cấp tự động chia range và giao dịch phân tán (TrueTime, v.v.) để đối với nhà phát triển chúng trông như một DB duy nhất. Như vậy, sharding đang dịch chuyển từ 'công nghệ mức thấp do nhà phát triển tự hiện thực' sang 'chức năng được quản lý do nền tảng cung cấp'.

6. Những điểm cần cân nhắc và hàm ý (góc nhìn Kỹ sư chuyên nghiệp)

  1. Thiết kế khóa shard quyết định thành bại. Để tránh điểm nóng — nơi dữ liệu·lưu lượng dồn vào một shard cụ thể — phải cẩn trọng chọn khóa có cardinality cao, phân tán đồng đều và khớp với mẫu truy vấn chủ đạo. Khóa shard chọn sai về sau rất khó thay đổi (phân phối lại toàn bộ), nên đây là quyết định cốt lõi ở giai đoạn thiết kế ban đầu.

  2. Mô hình hóa dữ liệu nhằm tối thiểu hóa phép toán xuyên shard. Cần thiết kế sao cho phần lớn truy vấn kết thúc trong một shard duy nhất bằng đồng vị trí — gom dữ liệu được truy vấn·cập nhật cùng nhau vào cùng shard —, phi chuẩn hóa, bảng tổng hợp chỉ dùng cho truy vấn, v.v. Đây là đánh đổi với nguyên tắc chuẩn hóa nên cần cân bằng phù hợp với đặc thù miền nghiệp vụ.

  3. Lựa chọn chiến lược nhất quán·giao dịch. Trong môi trường phân tán, đánh đổi CAP giữa tính nhất quán mạnh (2PC) và tính sẵn sàng·hiệu năng (nhất quán cuối cùng·Saga) là không thể tránh. Chiến lược thực tế là phân biệt vùng cần tính toàn vẹn mạnh như thanh toán với vùng cho phép trễ như thống kê để áp dụng mức nhất quán phân cấp.

  4. Vận hành·khả năng quan sát và thời điểm đưa vào. Sharding kéo theo độ phức tạp vận hành khi sao lưu·giám sát·thay đổi lược đồ·ứng phó sự cố đều tăng gấp bội. Do đó, cách tiếp cận theo giai đoạn là nên trụ trước bằng mở rộng dọc·bản sao đọc·cache, rồi mới đưa vào khi nút ghi đơn thực sự chạm giới hạn. Khi đưa vào, ưu tiên xem xét lựa chọn ủy thác gánh nặng mức thấp cho DB được quản lý·phân tán.

  5. Hướng tiến hóa của chiến lược mở rộng. Khi NoSQL·NewSQL·DB serverless (Aurora·Spanner·CockroachDB) cung cấp mặc định sharding tự động·rebalancing·giao dịch phân tán, gánh nặng ứng dụng tự sharding đang có xu hướng giảm dần. Từ góc nhìn Kỹ sư chuyên nghiệp, cốt lõi là phán đoán đánh đổi chi phí·linh hoạt giữa 'tự hiện thực vs ủy thác cho dịch vụ được quản lý' phù hợp với quy mô dữ liệu·năng lực đội ngũ·cấu trúc chi phí.

Tài liệu tham khảo


Tóm tắt một câu: Sharding là kỹ thuật phân chia ngang dữ liệu khối lượng lớn sang nhiều máy chủ DB để mở rộng tuyến tính (Scale-out) khả năng ghi·dung lượng; chiến lược phạm vi·băm (băm nhất quán)·thư mục cùng thiết kế khóa shard chi phối hiệu năng, nó được phân biệt với partitioning trong một máy chủ·replication dữ liệu giống nhau, và quản lý phép toán xuyên shard·giao dịch phân tán·rebalancing là thách thức cốt lõi.