Featured image of post Partitioning, Bucketing, Sharding, Replication, Edge: Mô hình tư duy chuẩn chỉ

Partitioning, Bucketing, Sharding, Replication, Edge: Mô hình tư duy chuẩn chỉ

Một mô hình tư duy gọn gàng về partitioning, bucketing, sharding, replication, và edge computing - khi nào dùng cái nào và tại sao chúng lại nằm ở các tầng khác nhau.

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:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
TỔ CHỨC DỮ LIỆU (bên trong một database instance)

    Partitioning
    Bucketing


PHÂN PHỐI DỮ LIỆU (trên nhiều database instances)

    Sharding
    Replication


ĐẶT COMPUTE Ở ĐÂU (code chạy chỗ nào)

    Edge computing

Đị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 clusternhiề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:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
Vấn đề là nghẽn throughput đọc hoặc CPU cao do quá nhiều request đồng thời?
    Yes -> Replication và caching, có thể là edge.

Vấn đề là độ trễ cho user ở xa tít mù khơi?
    Yes -> CDN và edge.

Vấn đề là một bảng quá to và query rùa bò?
    Yes -> Indexes, sửa lại query, rồi mới tới partitioning.

Vấn đề là một database không thể chịu nổi lượng ghi (writes) hoặc hết ổ cứng?
    Yes -> Sharding.

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:

1
2
3
4
5
bảng events

    events_2026_01
    events_2026_02
    events_2026_03

Ví dụ SQL:

1
2
3
4
CREATE TABLE events (
    id bigint,
    created_at timestamptz
) PARTITION BY RANGE (created_at);

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ụ:

1
2
3
4
5
6
bảng users

    bucket 0
    bucket 1
    bucket 2
    bucket 3

Logic kiểu kiểu như vầy:

1
2
3
4
5
import hashlib

def bucket_for(user_id, bucket_count):
    hash_val = int(hashlib.md5(str(user_id).encode()).hexdigest(), 16)
    return hash_val % bucket_count

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ụ ordersorder_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 ordersBucket 0 chỉ có thể khớp với order_itemsBucket 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:

1
2
3
4
5
# Database engine sẽ chạy cái này trên nhiều luồng
def parallel_join(buckets_count):
    for i in range(buckets_count):
        # Cặp này có thể join biệt lập hoàn toàn
        process_join(orders_bucket[i], items_bucket[i])

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ụ:

1
2
3
4
orders (đơn hàng)

    partition: 2026-01
    partition: 2026-02

Bucketing = chia theo băm (hash)

Ví dụ:

1
2
3
4
5
6
orders_2026-01

    bucket 0
    bucket 1
    bucket 2
    bucket 3

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ụ:

1
2
3
4
Shard 0 → DB instance A
Shard 1 → DB instance B
Shard 2 → DB instance C
Shard 3 → DB instance D

Routing kiểu vầy:

1
2
3

def shard_for(user_id, shard_count):
    return user_id % shard_count

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:

1
2
3
4
5
Một database instance

    bucket 0
    bucket 1
    bucket 2

Sharding:

1
2
3
Database instance A
Database instance B
Database instance C

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ụ:

1
2
3
4
5
Primary (Chính)

Replica A (Bản sao A)
Replica B (Bản sao B)
Replica C (Bản sao C)

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:

1
2
3
4
5
6
7
User

Edge location (Vị trí biên)

Origin API (Server gốc)

Origin database (DB gốc)

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:

  1. Indexes và tối ưu query
  2. Partitioning (khi bảng bắt đầu phình to)
  3. Replication (khi lượng đọc nhiều quá)
  4. Caching và edge (khi độ trễ và băng thông thành vấn đề)
  5. 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ạ

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
Tổ chức dữ liệu (Organize data)

    Partitioning
    Bucketing

Scale dung lượng (Scale capacity)

    Sharding

Tăng tính sẵn sàng (Increase availability)

    Replication

Giảm độ trễ (Reduce latency)

    Edge

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.

Được tạo với sự lười biếng tình yêu 🦥

Subscribe to My Newsletter