Database Sharding là gì? Khi scaling đỉnh cao đơn thuần không đủ

Database Sharding là gì? Khi scaling đỉnh cao đơn thuần không đủ

Database sharding (phân mảnh) là kỹ thuật chia dữ liệu trong một database lớn thành nhiều mảnh nhỏ hơn, độc lập, gọi là “shard”. Mỗi shard chứa một tập con của dữ liệu và có thể chạy trên server riêng biệt. Khi một ứng dụng đạt tới hàng triệu hoặc tỷ người dùng, single database (dù có replica) không thể đáp ứng được nhu cầu về throughput và latency — sharding trở thành giải pháp bắt buộc.

Khác với replication (sao chép dữ liệu để tăng khả năng đọc), sharding giảm tải cảread và write bằng cách phân tán load. Các công ty như Uber, Shopify, Discord và hàng chục công nghệ lớn đều áp dụng sharding để duy trì hiệu suất khi scale sang mức độ quy mô toàn cầu.

Minh họa cách sharding chia bảng users theo user_id ranges trên nhiều database server

3 chiến lược sharding chính: Hash, Range và Directory

Chọn shard key là bước then chốt. Dựa vào tính chất của key, ta có 3 phương pháp phổ biến:

  1. Hash-based Sharding: Áp dụng hàm hash (ví dụ: MD5, MurmurHash) trên shard key để quyết định shard_id. Đảm bảo phân tán đều, tránh hotspot nhưng khó thực hiện range queries.
  2. Range-based Sharding: Chia theo khoảng giá trị của shard key (ví dụ: user_id 0-9999 → shard 0, 10000-19999 → shard 1). Tối ưu cho range scans nhưng có nguy cơ uneven distribution nếu dữ liệu skew.
  3. Directory-based Sharding: Dùng lookup table (service discovery hoặc config server) để map key → shard. Linh hoạt nhất, cho phép resharding dễ dàng nhưng phụ thuộc thêm một thành phần độc lập.

Ví dụ thực tế: Hash-based phổ biến trong Cassandra và DynamoDB; Range-based trong HBase và Bigtable; Directory-based trong Vitess và MongoDB sharded cluster.

So sánh 3 chiến lược sharding bằng biểu đồ minh họa phân tán dữ liệu

Thách thức thực tế khi triển khai sharding

Sharding giải quyết vấn đề scale nhưng mang lại độ phức tạp mới mà các team DevOps và DBA cần chuẩn bị sẵn sàng:

  • Cross-shard transactions: Giao dịch liên quan đến nhiều shard (ví dụ: chuyển tiền giữa 2 tài khoản trên shard khác nhau) đòi hỏi 2PC hoặc saga pattern, làm tăng latency đáng kể.
  • Rebalancing và resharding: Khi một shard quá tải, cần di chuyển dữ liệu sang shard khác. Quy trình này thường tốn thời gian và cần downtime hoặc kỹ thuật clever như consistent hashing với virtual nodes.
  • Backup và disaster recovery: Sao shard riêng lẻ rồi ghép lại phải đảm bảo consistency point-in-time, đôi khi đòi dovuto áp dụng nails.
  • Monitoring và observability: Cần theo dõi metrics trên từng shard và tổng hợp để phát hiện hotspot hoặc shard thất bại.

Nhiều công ty bỏ qua bước thực nghiệm và trực tiếp áp dụng sharding vào production, dẫn đến incident nghiêm trọng khi peak load đến. Khuyến nghị bắt đầu từ môi trường staging với tập dữ liệu mô phỏng thực tế trước khi cutover.

Biểu đồ minh họa quy trình rebalancing shard khi thêm node mới vào cluster

Công cụ và framework hỗ trợ sharding hiện nay

Thay vì tự xây dựng sharding logic từ zero, các team có thể tận dụng những giải pháp đã grown:

Công cụ Loại database Phương pháp sharding Điểm nổi bật
Vitess MySQL-compatible Directory-based Được YouTube dùng để scale đến hàng tỷ queries/ngày
Citus PostgreSQL extension Hash-based Tích hợp seamless với Postgres, hỗ trợ SQL chuẩn
MongoDB Sharded Cluster DocumentDB Hash-based + Config server Automatic sharding và rebalancing
Apache Cassandra Wide-column store Hash-based (Murmur3Partitioner) Linear scalability, không có single point of failure
PlanetScale MySQL-compatible (Vitess) Directory-based Managed service, branching workflow như Git

Best practices để tránh pitfalls

Những bài học từ các triển khai sharding thất bại:

  1. Chọn shard key đúng: Tránh sử dụng timestamp hoặc sequential ID làm shard key — sẽ gây hotspot trên shard mới nhất. Ưu tiên các trường có cardinality cao và phân tán đều như user_id, UUID hoặc hash của email.
  2. Thiết kế schema shard-aware: Tránh foreign key liên qua shard nếu có thể. Nếu bắt buộc, phải thiết kế lại quan hệ hoặc sử dụng eventual consistency pattern.
  3. Bắt đầu với số shard hợp lý: Không bắt đầu với 256 shard nếu chỉ có 2 node. Mỗi shard cần đủ tài nguyên để hoạt động hiệu quả; quá nhiều shard dẫn đến overhead quản lý và tài nguyên bị lãng phí.
  4. Thiết lập alerts cho shard skew: Theo dõi kích thước và QPS của từng shard. Khi một shard đạt 80% capacity trong khi các shard khác chỉ 20%, cần lên kế hoạch rebalancing sớm.

Nguồn tham khảo: Vitess documentation, Citus documentation, MongoDB sharding guide.

Tôi là một lập trình viên IOS. Code chính là IOS nhưng thỉnnh thoảng vẫn đá sang Android hoặc web. Mặc dù không quá thông thạo nhưng tôi sẽ chia sẻ những kiến thức mà mình đã tìm hiểu, áp dụng qua.

Bài viết liên quan

C++ là gì? Tổng quan ngôn ngữ lập trình hệ thống hiệu năng cao

C++ là gì? Tổng quan ngôn ngữ lập trình hệ thống hiệu năng cao C++ là ngôn ngữ lập trình đa năng, hiệu năng cao, được sử dụng rộng rãi…

Xem thêm

Effective Go: Generics, Interfaces và Error Handling Patterns

Effective Go 2024: Generics, Interfaces và Error Handling Patterns Go 1.18 ra mắt generics năm 2022, nhưng đến 2024 mới thực sự định hình thành các patterns phổ biến trong…

Xem thêm

Zig Package Manager: quản lý dependencies và build cross-compiler tự động

Zig Package Manager là gì? Zig Package Manager (ZPM) là hệ thống quản lý dependencies tích hợp sẵn trong ngôn ngữ lập trình Zig, ra đời để giải quyết bài…

Xem thêm
0 0 đánh giá
Article Rating
Theo dõi
Thông báo của
guest
0 Comments
Cũ nhất
Mới nhất Được bỏ phiếu nhiều nhất