Anh em dev nhà mình rất hay nhầm lẫn lung tung giữa partitioning, bucketing, sharding, và replication.
Edge computing thì ít khi bị nhầm với mấy món kia, nhưng lại hay bị đề xuất sai kiểu như một giải pháp thay thế (kiểu: “ê hay là dùng edge thay cho sharding đi”).
Mấy khái niệm này nó nằm ở các tầng (layers) khác nhau và giải quyết những vấn đề nghẽn cổ chai (bottlenecks) hoàn toàn khác nhau.
Bài viết này sẽ trang bị cho bạn một mô hình tư duy (mental model) sạch đẹp và các ví dụ thực tế để lần sau chọn đồ chơi cho chuẩn.
Một sơ đồ duy nhất cần nhớ
Tất cả mọi thứ trong bài này đều quy về cái cấu trúc phân cấp này:
| |
Định nghĩa nhanh (mỗi cái một câu)
Partitioning Chia nhỏ một bảng to thành các phần logic nhỏ hơn bên trong một database để giảm chi phí quét (scan) và bảo trì.
Bucketing Băm (hash) các dòng dữ liệu vào các nhóm cố định bên trong một database để tối ưu cho việc join và quét song song.
Sharding Chia nhỏ dữ liệu ra nhiều database instances khác nhau để mở rộng dung lượng lưu trữ và khả năng ghi (write throughput).
Replication Sao chép dữ liệu y chang nhau ra nhiều node để tăng tính sẵn sàng (availability) và khả năng chịu tải đọc (read scalability).
Edge computing Chạy tính toán (compute) ở gần người dùng nhất có thể để giảm độ trễ (latency).
Mô hình thực tế dễ hình dung: Kho hàng
Tưởng tượng một shop online bán hàng với các gói kiện.
- Một database instance là một cái kho.
- Một database cluster là nhiều cái kho.
- Users là khách hàng rải rác khắp thế giới.
Giờ map các thuật ngữ nhé:
- Partitioning: Chia gói hàng vào các khu vực riêng biệt như “Tháng 1”, “Tháng 2”, “Hàng hoàn trả”, để nhân viên đỡ phải chạy đi tìm lung tung.
- Bucketing: Bên trong mỗi khu vực, chia gói hàng vào các làn cố định (Làn 0..31) bằng cách băm (hash) mã đơn hàng.
- Sharding: Mở thêm kho mới; mỗi kho sẽ chịu trách nhiệm một phần đơn hàng.
- Replication: Giữ các bản sao hàng hóa y hệt nhau ở nhiều kho khác nhau để lỡ kho này cháy thì còn kho kia, và để nhiều người cùng lấy hàng được.
- Edge computing: Đặt mấy cái trạm trung chuyển nhỏ xíu ngay gần nhà khách để xử lý mấy yêu cầu đơn giản nhanh gọn lẹ (chủ yếu là caching + điều hướng).
Nếu bạn thích kiểu ghi nhớ theo hành động:
- Partitioning: chia theo giá trị (value)
- Bucketing: chia theo băm (hash)
- Sharding: chia ra nhiều kho
- Replication: copy ra nhiều kho
- Edge: mang compute lại gần khách
Cây quyết định trong 30 giây
Khi ai đó phán “chúng ta cần sharding”, hãy lôi checklist này ra:
| |
Layer 1: Partitioning (chia theo giá trị)
Partitioning chia một bảng logic to đùng thành các phân đoạn logic nhỏ hơn, vẫn nằm trong cùng một database.
Ví dụ cấu trúc:
| |
Ví dụ SQL:
| |
Tại sao Partitioning tồn tại:
- Query nhanh hơn nhờ partition pruning (chỉ tìm trong phân vùng cần thiết)
- Xóa và lưu trữ lịch sử (archival) nhanh hơn
- Index nhỏ hơn
- Bảo trì dễ thở hơn
Cái mà Partitioning KHÔNG làm được:
- Không làm tăng tổng dung lượng lưu trữ
- Không làm tăng khả năng ghi (write throughput) vượt quá giới hạn của một database
Layer 2: Bucketing (phân phối hash bên trong 1 database)
Bucketing chia các dòng dữ liệu vào một số lượng bucket cố định dùng hàm hash.
Ví dụ:
| |
Logic kiểu kiểu như vầy:
| |
Tại sao Bucketing tồn tại:
- Join nhanh hơn (vì dữ liệu liên quan nằm cùng chỗ)
- Xử lý song song (parallelism) tốt hơn
- Giảm bớt lượng dữ liệu phải quét (scan)
Cái hay của Join & Parallelism
Bucketing thực sự tỏa sáng khi bạn có hai bảng lớn (ví dụ orders và order_items) và cả hai đều được bucketing theo cùng một key (order_id) với cùng số lượng bucket.
1. Co-located Joins (Gom cụm dữ liệu)
Trong các hệ thống phân tán, việc join hai bảng lớn thường gây ra hiện tượng Shuffle Join. Database engine phải lôi hàng triệu dòng dữ liệu chạy loăng quăng trên hạ tầng mạng (giống như việc điều động hàng đoàn xe tải chạy qua lại giữa các kho hàng) để các ID khớp nhau cuối cùng cũng nằm chung một chỗ. Cái “vụ kẹt xe” trên mạng này chính là nguyên nhân gây chậm trễ hàng đầu.
Với Bucketing, database sẽ thực hiện Bucket-to-Bucket Join. Vì nó biết chắc chắn rằng orders ở Bucket 0 chỉ có thể khớp với order_items ở Bucket 0, và cả hai đã nằm sẵn trên cùng một ổ cứng, nó sẽ bỏ qua hoàn toàn bước “Shuffle”. Không điều xe, không kẹt xe.
2. Xử lý song song độc lập
Vì các cặp bucket này hoàn toàn độc lập, bạn có thể quăng 32 cặp bucket cho 32 worker (CPU core) xử lý cùng một lúc. Không ông nào cần đợi ông nào, cũng không cần trao đổi dữ liệu chéo nhau.
Ví dụ mã giả cho việc join song song:
| |
Ràng buộc quan trọng:
Tất cả các bucket vẫn nằm chung trong cùng một database hoặc hệ thống lưu trữ.
Bucketing cải thiện hiệu năng (performance), không phải dung lượng (capacity).
Partitioning vs Bucketing
Partitioning = chia theo giá trị (value)
Ví dụ:
| |
Bucketing = chia theo băm (hash)
Ví dụ:
| |
Thực tế thì: partitioning giúp giảm phạm vi quét; bucketing giúp join và xử lý song song hiệu quả hơn.
Người ta thường dùng cả hai cùng lúc.
Layer 3: Sharding (phân tán trên nhiều database)
Sharding chia dữ liệu ra nằm trên nhiều database instances khác nhau.
Ví dụ:
| |
Routing kiểu vầy:
| |
Tại sao Sharding tồn tại:
- Tăng tổng dung lượng lưu trữ
- Tăng khả năng ghi (Write throughput)
- Tăng số lượng kết nối (Connection capacity)
Đánh đổi:
- Query chéo shard (Cross-shard queries) siêu phức tạp
- Transaction khó nhằn
- Cân bằng lại dữ liệu (Rebalancing) là một cực hình
Bucketing vs Sharding (khác biệt cốt lõi)
Cả hai đều dùng phân phối kiểu hash.
Khác nhau ở cái phạm vi (scope).
Bucketing:
| |
Sharding:
| |
Bucketing cải thiện hiệu năng bên trong một database.
Sharding mở rộng dung lượng trên nhiều database.
Layer 4: Replication (sao chép dữ liệu)
Replication tạo ra các bản sao y hệt nhau của dữ liệu trên nhiều node.
Ví dụ:
| |
Tại sao Replication tồn tại:
- Tính sẵn sàng cao (High availability)
- Dự phòng (Failover)
- Scale khả năng đọc (Read scaling)
Replication không giúp tăng khả năng ghi.
Sharding vs Replication (khác biệt về dữ liệu)
Cả hai đều dùng nhiều server, nhưng cách xử lý dữ liệu thì trái ngược nhau.
Replication: tất cả server đều có tất cả dữ liệu giống hệt nhau (clones).
- Mục tiêu: Tăng khả năng đọc và tính sẵn sàng.
- Giới hạn: Bạn vẫn bị giới hạn bởi dung lượng ổ cứng của một con máy duy nhất.
Sharding: mỗi server chỉ giữ một mẩu dữ liệu (splits).
- Mục tiêu: Tăng khả năng ghi và tổng dung lượng lưu trữ.
- Giới hạn: Query chéo shard và transaction cực kỳ phức tạp.
Layer 5: Edge computing (mang compute lại gần user)
Edge computing di dời việc tính toán đến các địa điểm gần người dùng hơn.
Luồng đi điển hình:
| |
Edge cải thiện độ trễ và trải nghiệm người dùng, thường là thông qua caching và điều hướng request.
Edge không làm thay đổi dung lượng database.
Hệ thống thực tế tiến hóa như thế nào
Lộ trình điển hình:
- Indexes và tối ưu query
- Partitioning (khi bảng bắt đầu phình to)
- Replication (khi lượng đọc nhiều quá)
- Caching và edge (khi độ trễ và băng thông thành vấn đề)
- Sharding (chỉ khi một con primary không thể gồng nổi nữa)
Hầu hết các hệ thống chả bao giờ cần tới bước 5 đâu.
Mô hình tư duy chốt hạ
| |
Mỗi thuật ngữ ứng với một điểm nghẽn khác nhau.
Cách nhanh nhất để rớt bài review thiết kế hệ thống là dùng đúng từ chuyên ngành nhưng sai tầng lớp.
