Chuyển tới nội dung chính

Cách Sharding trong Cơ sở dữ liệu Hoạt động

Sharding là gì?

Sharding (Phân mảnh), còn gọi là Phân vùng theo chiều ngang (Horizontal Partitioning), chia một tập dữ liệu lớn (Dataset) thành các phần nhỏ hơn gọi là Shard (Mảnh), mỗi phần được lưu trữ trên một máy chủ cơ sở dữ liệu riêng biệt. Thay vì một máy khổng lồ chứa mọi thứ, dữ liệu được phân phối (Distributed) trên một cụm (Cluster) nhiều máy.

Sharding khác với Replication (Sao chép) — Replication sao chép cùng một dữ liệu đến nhiều Nodes để đảm bảo tính sẵn sàng (Availability), trong khi Sharding phân phối khác dữ liệu đến các Nodes khác nhau để mở rộng khả năng (Scalability).

Tại sao cần Sharding?

Vấn đềSharding giúp gì
Dữ liệu quá lớn cho một máyMỗi Shard giữ một phần (Subset) — tổng dung lượng = tổng tất cả các Shard
Nút thắt thông lượng ghi (Write Throughput Bottleneck)Ghi được phân tán (Spread) across các Shard — không có Node đơn lẻ phải xử lý tất cả
Độ trễ truy vấn cao (High Query Latency)Mỗi Shard lập chỉ mục (Index) tập dữ liệu nhỏ hơn — truy vấn chạy nhanh hơn
Chi phíSử dụng nhiều máy phổ thông (Commodity Machines) thay vì một máy chủ đắt tiền

Thuật ngữ quan trọng (Key Terminology)

  • Shard Key (Khóa phân mảnh) — cột (hoặc tập hợp các cột) dùng để quyết định Shard nào chứa một dòng (Row) (ví dụ: user_id, region)
  • Shard Router (Bộ định tuyến) — thành phần chặn truy vấn và chuyển tiếp đến Shard đúng
  • Hash Function (Hàm băm) — hàm ánh xạ Shard Key đến số Shard (ví dụ: hash(key) % num_shards)
  • Hotspot (Điểm nóng) — một Shard nhận lượng truy cập nhiều hơn đáng kể so với các Shard khác
  • Resharding (Tái phân mảnh) — quá trình phân phối lại dữ liệu khi thêm hoặc xóa Shard

Cách Sharding hoạt động (đơn giản hóa)

1. Client sends a query (read or write) with a shard key
2. Router evaluates the shard key → determines target shard
3. Router forwards the query to the target shard only
4. Target shard processes the query
5. Router collects the result and returns it to the client

Quyết định thiết kế quan trọng là: làm sao Router quyết định Shard nào được sử dụng? Điều này quyết định chiến lược Sharding (Sharding Strategy).

Trực quan hóa

Xem cách các thao tác ghi được định tuyến đến các Shard khác nhau dưới ba chiến lược phổ biến. Chuyển đổi giữa các chế độ để so sánh phân phối (Distribution), mẫu truy vấn (Query Patterns) và đánh đổi (Trade-offs):

Applies a hash function to the shard key and uses modulo to assign data to shards. Provides even distribution but makes range queries across shards expensive.

0 / 0
💻Client
🔀
Shard Router

So sánh các chiến lược Sharding

Khía cạnhDựa trên Hash (Hash-Based)Dựa trên Range (Range-Based)Dựa trên Directory (Directory-Based)
Định tuyến (Routing)hash(key) % N → số ShardKhoảng giá trị Key → ShardBảng tra cứu ánh xạ Key → Shard
Phân phối (Distribution)Đồng đều (nếu Hash đồng nhất)Không đồng đều nếu phân bố Key bị lệchCó thể cấu hình — ánh xạ tùy ý
Truy vấn RangeTốn kém — phải truy vấn tất cả ShardHiệu quả — truy vấn đến một ShardPhụ thuộc vào ánh xạ
Thêm ShardCần Resharding hầu hết dữ liệuThêm Range mới, di chuyển dữ liệu biênChỉ cập nhật bảng tra cứu
Độ phức tạpThấp — chỉ Hash + ModuloThấp — kiểm tra RangeTrung bình — duy trì bảng tra cứu
Nguy cơ HotspotThấpCao (ví dụ: Timestamp gần đây)Phụ thuộc vào thiết kế ánh xạ
Trường hợp sử dụngUser ID, Session TokenChuỗi thời gian (Time-series), dữ liệu đã sắp xếpPhân tán theo địa lý (Geo-distributed), Multi-tenant

Chọn Shard Key

Shard Key quyết định mọi thứ về hiệu năng Sharding của bạn. Shard Key tồi dẫn đến Hotspot, truy vấn Cross-shard và Resharding đau đớn.

Tính chất của Shard Key tốt

  1. Độ phân biệt cao (High Cardinality) — nhiều giá trị khác nhau để dữ liệu phân bổ đồng đều
  2. Tần suất thấp (Low Frequency) — không có giá trị đơn lẻ nào chiếm ưu thế (tránh Hotspot)
  3. Liên quan đến truy vấn (Query-relevant) — hầu hết truy vấn bao gồm Shard Key nên chỉ truy cập một Shard
  4. Bất biến (Immutable) — thay đổi Shard Key nghĩa là phải di chuyển dòng sang Shard khác

Lựa chọn Shard Key phổ biến

Shard KeyChiến lượcGhi chú
user_idHashPhân phối người dùng đồng đều; truy vấn cho một người dùng chỉ truy cập một Shard
created_atRangePhù hợp cho chuỗi thời gian; dữ liệu gần đây tạo Hotspot ở Shard "hiện tại"
regionDirectorySharding theo địa lý; dữ liệu mỗi vùng nằm trong Data Center gần đó
tenant_idHash hoặc DirectorySaaS Multi-tenant; cách ly Tenant ở cấp Shard

Thách thức của Sharding

Truy vấn Cross-shard (Cross-shard Queries)

Các truy vấn không bao gồm Shard Key phải được gửi đến tất cả Shard và kết quả được gộp lại. Điều này gọi là truy vấn Scatter-gather và chậm hơn nhiều so với truy vấn có định hướng.

JOIN across Shard (Cross-shard JOINs)

JOIN giữa các bảng trên Shard khác nhau rất tốn kém hoặc không được hỗ trợ. Các giải pháp thay thế phổ biến:

  • Nhân đôi bảng nhỏ (Duplicate Small Tables) đến mọi Shard (dữ liệu tham chiếu - Reference Data)
  • JOIN ở mức ứng dụng (Application-level JOINs) — truy vấn từng Shard riêng biệt, gộp kết quả trong Code
  • Co-shard các bảng liên quan — sử dụng cùng Shard Key cho các bảng có liên quan

Resharding (Tái phân mảnh)

Khi bạn thêm hoặc xóa Shard, dữ liệu phải được phân phối lại. Các phương pháp:

  • Consistent Hashing (Băm nhất quán) — giảm thiểu di chuyển dữ liệu khi thêm/xóa Shard
  • Double-write (Ghi kép) — ghi vào cả bố cục Shard cũ và mới trong quá trình Migration
  • Online Migration (Di chuyển trực tuyến) — các công cụ như Vitess hoặc Balancer của MongoDB di chuyển dữ liệu từng phần

Sharding trong Thực tế

  • MongoDB: Sharding native với Mongos Router. Hỗ trợ Shard Key Hash và Range. Auto-balancer di chuyển các Chunk giữa các Shard.
  • PostgreSQL: Không có Sharding native. Sử dụng Citus Extension, Pgpool-II hoặc Sharding ở mức ứng dụng. Table Partitioning tích hợp sẵn (không phải Sharding thực sự — cùng một máy chủ).
  • MySQL: Sử dụng Vitess (được YouTube sử dụng) hoặc Sharding ở mức ứng dụng. MySQL Cluster (NDB) có Automatic Sharding.
  • Redis Cluster: Sharding dựa trên Hash với 16384 Hash Slot. Mỗi Node sở hữu một khoảng Slot. Hỗ trợ Resharding không gây gián đoạn (Zero Downtime).

Khi nào nên Sharding

Sharding thêm độ phức tạp đáng kể. Chỉ nên xem xét Sharding khi:

  1. Bạn đã chạm đến giới hạn mở rộng theo chiều dọc (Vertical Scaling Limits) — không thể thêm CPU/RAM cho một máy duy nhất
  2. Read Replica chưa đủ — ghi mới là điểm nghẽn (Bottleneck), không phải đọc
  3. Tập dữ liệu vượt quá dung lượng lưu trữ của một máy — dữ liệu không vừa trên một ổ đĩa
  4. Bạn cần định vị dữ liệu đa vùng (Multi-region Data Locality) — người dùng ở các vùng khác nhau cần dữ liệu cục bộ

Nếu bạn chưa chạm đến các giới hạn này, hãy bắt đầu với Replication và mở rộng theo chiều dọc trước. Sharding quá sớm (Premature Sharding) là nguyên nhân phổ biến gây ra độ phức tạp không cần thiết.

Tìm hiểu thêm

Đọc lý thuyết đầy đủ tại Cơ sở dữ liệu > Thiết kế Cơ sở dữ liệu.