---
title: "Thiết kế database nhiều shard - shard key, hot key, lookup index và reshard"
description: "Khóa học về chia database Postgres ra nhiều shard xoay quanh bài toán định tuyến lệnh đọc và ghi giữa các máy. Bạn sẽ biết cách chọn shard key, xử lý hot key, thiết kế lookup index và dời dữ liệu an toàn khi app vẫn đang chạy. Hệ thống được mở rộng dựa trên số liệu đo đạc thực tế thay vì chia nhỏ database vội vã."
canonical: "https://200lab.io/courses/thiet-ke-database-nhieu-shard-shard-key-hot-key-lookup-index-va-reshard"
type: "course"
course_type: "course"
learning_type: "free_form"
published: "2026-10-10T05:00:11Z"
students: 28
---

## Khóa học này mang lại gì cho bạn

Khi app của bạn cùng AI agent xây dựng lớn dần, database chính nhận mọi lệnh ghi (primary) bắt đầu chạm ngưỡng giới hạn. Bạn đã thêm replica để san sẻ lệnh đọc và chia partition cho các bảng lớn trên cùng một máy, nhưng ổ đĩa vẫn bận suốt giờ cao điểm và agent đề xuất chia dữ liệu ra nhiều shard. Khóa học mang lại bảy năng lực cụ thể giúp bạn làm chủ quyết định kiến trúc trước khi can thiệp vào database:

- **Biết khi nào chưa cần chia database** — Bạn phân tích bảng tỉ lệ lệnh ghi theo nhóm bảng để nhận ra thời điểm chỉ cần tách theo chức năng sang database riêng thay vì chia nhỏ bảng theo dòng, đồng thời giải thích được vì sao replica và partition không giúp tăng trần ghi của máy.
- **Chọn shard key theo truy vấn chính** — Bạn xác định được cột giúp lệnh ghi mới trải đều và phần lớn lượt đọc chỉ cần hỏi một shard duy nhất, đồng thời co-location các bảng liên quan trong cùng transaction tạo đơn để bảo toàn tính toàn vẹn dữ liệu.
- **Xử lý hot key hiệu quả** — Bạn phát hiện chính xác hiện tượng nghẽn do tranh chấp lock dòng khi CPU database còn thấp mà thời gian phản hồi p99 vẫn tăng cao, từ đó áp dụng giải pháp phân tán tải phù hợp với từng loại dữ liệu cụ thể.
- **Tìm đúng database cho từng key** — Bạn thiết kế bảng thư mục quản lý 256 logical shard để khi thêm database thứ năm chỉ phải chép khoảng 20% dữ liệu với điều kiện các logical shard có dung lượng gần nhau, đồng thời cấu hình mã đơn mang thông tin logical shard để callback thanh toán chỉ cần hỏi đúng một shard.
- **Xử lý truy vấn không có shard key** — Bạn xây dựng lookup index cập nhật qua outbox để các màn hình tra cứu không phải gửi request tới mọi shard, kết hợp bảng toàn cục để chặn trùng lặp handle của shop trên phạm vi toàn hệ thống.
- **Chuyển dữ liệu khi app vẫn nhận lệnh ghi** — Bạn vận hành quy trình chuyển dữ liệu bốn bước gồm backfill theo lô, bắt thay đổi, xác minh cùng mốc và cutover, kết hợp epoch trên từng entry để database từ chối dứt khoát các lệnh ghi muộn.
- **Hỏi agent đúng số liệu trước khi đồng ý** — Bạn chủ động yêu cầu agent cung cấp chính xác tỉ lệ ghi theo nhóm bảng, phần trăm truy vấn phải hỏi mọi shard, khối lượng dữ liệu phải chép và thời gian dừng ghi lúc cutover trước khi phê duyệt bất kỳ đề xuất nào.

Khóa học dùng Postgres làm môi trường phân tích và không phụ thuộc vào công cụ sharding cụ thể: code minh họa bằng TypeScript và SQL ngắn gọn, tập trung vào bản chất luồng dữ liệu và các tradeoff kiến trúc thực tế.

## Khóa học cung cấp những nền tảng nào

Toàn bộ khóa học được xây dựng xoay quanh một câu hỏi cốt lõi: khi dữ liệu đã phân tán trên nhiều database, mỗi lệnh đọc và lệnh ghi phải đi tới database nào để hệ thống vận hành chính xác và ổn định. Thực tế phát triển từ [Herding elephants: Lessons learned from sharding Postgres at Notion](https://www.notion.com/blog/sharding-postgres-at-notion) khi chia 480 logical shard trên 32 database, kinh nghiệm từ [The growing pains of database architecture](https://www.figma.com/blog/how-figma-scaled-to-multiple-databases/) của Figma khi tách database theo chức năng trước khi chia dòng, và giải pháp từ [Shard Balancing: Moving Shops Confidently with Zero-Downtime at Terabyte-scale](https://shopify.engineering/mysql-database-shard-balancing-terabyte-scale) của Shopify về chuyển dữ liệu giữa các shard đều cho thấy việc nắm vững luồng dữ liệu quan trọng hơn chọn công cụ. Năm nhóm nội dung dưới đây giúp bạn lần lượt làm chủ các nấc thang mở rộng của hệ thống.

### 1. Khi nào chưa cần chia database, và partition trên một máy giúp được tới đâu

Khi disk của primary bận tới 90% thời gian giờ cao điểm, phản xạ chia nhỏ mọi bảng thành 8 shard thường khiến hệ thống phức tạp không cần thiết. Phân tích thực tế cho thấy nhóm bảng chat chiếm 62% lệnh ghi và 1,1 TB dữ liệu nhưng ít join với phần còn lại, nên chỉ cần chuyển riêng nhóm này sang một database độc lập là database chính đã hạ tải rõ rệt. Bài học giúp bạn phân biệt rõ giữa việc tách database theo chức năng và việc xẻ dọc bảng theo dòng bằng sharding. Bạn cũng sẽ đánh giá đúng năng lực của partition trên một máy đơn lẻ trong việc dọn dữ liệu cũ, hiểu vì sao partition không nâng được trần ghi phần cứng, và nắm vững ba tiêu chí so sánh giữa tự làm routing trong app với việc sử dụng các database có sẵn tính năng sharding.

### 2. Chọn shard key và xử lý hot key

Chọn cột thời gian tăng dần làm shard key sẽ dồn toàn bộ đơn hàng mới vào shard của tháng hiện tại, đẩy CPU máy đó lên 95% trong khi các máy còn lại gần như rảnh. Bạn sẽ học cách chọn shard key giúp lệnh ghi phân bổ đều và phần lớn lượt đọc chỉ cần hỏi một shard duy nhất, đồng thời co-location bảng đơn hàng, dòng hàng và thanh toán trên cùng shard key để giữ transaction trọn vẹn. Khi một sản phẩm nhận hàng nghìn lệnh ghi mỗi giây khiến p99 tăng vọt dù CPU database chỉ ở mức 30%, bạn sẽ nhận diện được nút thắt nằm ở việc tranh chấp lock dòng và cạn kiệt connection pool. Nhóm bài phân tích ba phương án xử lý hot key theo từng loại dữ liệu, áp dụng đếm trong bộ nhớ và ghi gộp cho lượt xem, và giải quyết triệt để tình huống checkout flash sale bằng cách chia nhỏ dòng tồn kho kết hợp trừ có điều kiện.

### 3. Tìm đúng database cho một key và sinh ID không trùng giữa các shard

Việc chọn database theo phép chia lấy dư số lượng máy khiến lần thêm database thứ năm trong ví dụ phải chuyển dịch tới 80% dữ liệu của toàn bộ hệ thống. Bạn sẽ tìm hiểu cách tách rời vị trí của key khỏi số lượng database bằng consistent hashing và giải pháp sử dụng bảng thư mục quản lý 256 logical shard cố định. Khi dữ liệu chia ra nhiều shard, việc giữ nguyên cột tự tăng khiến các database cấp trùng mã đơn, dẫn đến callback thanh toán cập nhật nhầm đơn hàng của shop khác. Nhóm bài so sánh năm phương pháp sinh khóa chính phân tán, làm rõ lý do chọn ID 64 bit mang thông tin logical shard cho luồng thanh toán, và lưu ý quan trọng khi truyền ID 64 bit qua chuỗi JSON trong môi trường TypeScript.

### 4. Truy vấn không có shard key và giá trị phải unique trên mọi shard

Truy vấn tìm đơn theo số điện thoại không chứa shard key buộc app phải dùng scatter-gather gửi request tới cả 8 database, khiến thời gian phản hồi bị kéo dài theo database chậm nhất đang chạy backup. Bạn sẽ xây dựng lookup index đặt tại database riêng và cập nhật bất đồng bộ qua outbox worker, giúp lượt tra cứu chỉ cần hỏi đúng shard chứa dữ liệu. Bên cạnh đó, bài học chỉ ra vì sao unique constraint của Postgres mất tác dụng trên nhiều database độc lập, dẫn đến sự cố trùng lặp handle đường dẫn shop giữa các shard. Bạn sẽ thiết lập bảng toàn cục quản lý handle với cơ chế giữ chỗ trước, đồng thời hiểu rõ vai trò và giới hạn của saga cùng 2PC khi phải cập nhật dữ liệu trên hai shard khác nhau.

### 5. Chuyển dữ liệu sang database khác khi app vẫn ghi

Phương pháp dump và restore truyền thống thường làm thất thoát hàng chục nghìn bản ghi được cập nhật trong suốt nhiều giờ chuyển đổi. Bạn sẽ làm chủ quy trình chuyển dữ liệu trực tiếp qua bốn bước chuẩn xác: backfill theo lô có checkpoint và giới hạn tốc độ, bắt thay đổi mới từ trước mốc chép, xác minh checksum hai bên và cutover an toàn trong vài giây. Để giải quyết triệt để việc app vẫn ghi nhầm vào database cũ do cache routing chưa hết hạn, bạn sẽ gắn epoch cho từng entry trong bảng thư mục để database nguồn chủ động từ chối lệnh ghi muộn bằng lỗi moved. Nhóm bài khép lại với kỹ thuật reshard cân bằng lại dung lượng khi một database đầy nhanh gấp đôi, và tình huống chuyển riêng một kênh livestream đang quá tải sang database mới mà không làm mất tin nhắn.

## Vì sao 200Lab tạo ra khóa học này

Trong thời đại AI agent có thể sinh toàn bộ code routing chỉ sau vài câu lệnh prompt, việc chia database ra nhiều shard trông có vẻ rất dễ dàng. Agent có thể nhanh chóng dựng cấu hình, viết hàm chia lấy dư và triển khai hệ thống chạy thử nghiệm trên môi trường staging chỉ trong một buổi làm việc. Thế nhưng, rủi ro lớn nhất thường xuất hiện trước khi dòng code đầu tiên được viết ra: bạn chưa xác định được hệ thống đã thực sự cần chia hay chưa, và nên chọn cột nào làm shard key.

Chọn sai shard key hiếm khi phát tác lỗi ngay lập tức. Các bài kiểm thử đơn giản vẫn vượt qua, biểu đồ ghi dữ liệu ban đầu trông rất cân bằng, cho tới khi một màn hình tra cứu phổ biến phải hỏi toàn bộ database trong cụm khiến thời gian phản hồi tăng gấp mười lần. Khi phát hiện ra sai lầm, việc thay đổi cách phân vùng đòi hỏi phải phân phối lại toàn bộ dữ liệu trong lúc người dùng vẫn đang liên tục gửi request. Người phải trực tiếp chịu trách nhiệm rà soát từng giao dịch lỗi và giải thích sự cố với khách hàng chính là bạn chứ không phải agent.

Các hệ thống quy mô lớn trên thế giới đều từng trải qua những bài học tương tự. Figma từng ưu tiên bóc tách các nhóm bảng độc lập trước khi nghĩ tới sharding, Notion kiên trì tổ chức dữ liệu theo nhóm logical shard cố định, và Slack từng chứng kiến các shard chứa khách hàng lớn làm nghẽn toàn bộ tài nguyên dùng chung. Ở mỗi nơi, bài học đều gắn với bài toán riêng: Figma đo tải và transaction kỹ lưỡng trước khi tách database, Notion dùng logical shard để kiểm soát di dời dữ liệu, còn Slack xử lý shard bị quá tải vì khách hàng lớn.

200Lab xây dựng khóa học này nhằm trang bị cho bạn nền tảng tư duy và số liệu vững chắc trước khi ra quyết định kỹ thuật. Từng tình huống trong chương trình đều gắn liền với một quyết định cụ thể: tách bảng nào, chọn key nào, sinh ID ra sao và kiểm soát quyền ghi thế nào. Sau khóa học, bạn sẽ tự tin trao đổi giải pháp với toàn đội ngũ, bảo vệ phương án bằng các phân tích tradeoff rõ ràng, và biết chính xác thời điểm nào chỉ cần tối ưu trên một máy để tiết kiệm tối đa chi phí vận hành hạ tầng.

## Những vấn đề thường gặp khi chia database ra nhiều shard

Khi database có dấu hiệu chậm lại, phản xạ thông thường là nâng cấp phần cứng hoặc chia nhỏ database ngay lập tức. Tuy nhiên, các sự cố thực tế dưới đây đòi hỏi bạn phải nắm rõ luồng ghi, đặc tính truy vấn và vị trí chính xác của dữ liệu trước khi xử lý:

- Đề xuất chia toàn bộ database ra 8 shard khi disk primary bận 90% giờ cao điểm — Nhóm bảng chat chiếm phần lớn lệnh ghi nhưng ít liên kết với nghiệp vụ chính, chỉ cần tách riêng nhóm này sang database độc lập là đủ giải tỏa áp lực mà chưa cần sharding.
- Phân chia theo tháng khiến shard tháng hiện tại chạm 95% CPU còn các shard khác rảnh — Cột thời gian tăng dần dồn toàn bộ lệnh ghi mới vào phân vùng cuối cùng, khiến dữ liệu cũ thì đều nhưng tải mới lại tập trung cục bộ.
- Lệnh ghi phân bổ đều nhưng thời gian phản hồi trang danh sách đơn tăng từ 150 ms lên 1,4 giây — Trang nghiệp vụ lọc theo cột khác với shard key nên app phải gửi truy vấn tới toàn bộ các shard rồi chờ máy chậm nhất phản hồi.
- CPU database chỉ ở mức 30% nhưng p99 của API trang sản phẩm tăng vọt lên 2,4 giây — Request phải xếp hàng chờ lock trên một dòng dữ liệu nóng và chiếm dụng hết connection pool, khiến việc nâng cấp tài nguyên server không mang lại hiệu quả.
- Kế hoạch thêm database thứ năm yêu cầu chép lại 80% dữ liệu của toàn hệ thống — Công thức định tuyến dùng phép chia lấy dư gắn liền với số lượng máy, khiến việc đổi số chia làm đảo lộn vị trí của hầu hết các dòng dữ liệu.
- Callback cổng thanh toán cập nhật nhầm trạng thái giữa đơn hàng của hai shop — Các shard dùng bộ đếm riêng tự tăng từ cùng một mốc khởi đầu, dẫn đến việc cấp trùng khóa chính cho hai bản ghi độc lập.
- Dump và restore cả bảng suốt đêm nhưng sáng ra hai database lệch 38.000 bản ghi — Phương pháp sao chép tĩnh chỉ lấy dữ liệu tại mốc bắt đầu, bỏ sót toàn bộ các lệnh ghi phát sinh trong lúc tiến trình chép đang chạy.
- Đã chuyển shard và đổi bảng thư mục nhưng cuối ngày vẫn có 27 đơn ghi vào database cũ — Bản cache routing trong bộ nhớ của app chưa hết hạn và database cũ thiếu cơ chế epoch để nhận diện và từ chối lệnh ghi gửi nhầm.

Mỗi vấn đề trên đều được phân tích cặn kẽ trong khóa học, đi kèm công thức tính toán và bộ câu hỏi đối soát cụ thể để bạn làm việc hiệu quả với AI agent.

## Bạn sẽ học theo cách nào

- **Bắt đầu từ tín hiệu kỹ thuật thực tế** — Mỗi bài học đều xuất phát từ một triệu chứng có thật trên hệ thống như mức tải disk, biểu đồ trễ p99, log cảnh báo hoặc số liệu đo đạc từ load test, giúp bạn định hình chính xác vấn đề cần giải quyết.
- **Phân tích qua mô hình thu nhỏ** — Trước khi bước vào nghiệp vụ lớn, bạn luôn tiếp cận cơ chế qua ví dụ tinh gọn với vài shard và vài key cụ thể để theo dõi đường đi của từng bản ghi và bản chất của thuật toán.
- **Ra quyết định dựa trên số liệu và tradeoff** — Mọi lựa chọn về shard key, cấu trúc bảng thư mục hay phương án chuyển dịch dữ liệu đều được cân đo bằng số liệu thực tế, đi kèm các phân tích thiệt hơn rõ ràng cho từng phương án.
- **Rèn luyện tư duy qua bài toán tự tính** — Các bài học cơ chế cung cấp câu hỏi tính toán ngắn để bạn tự tay ước lượng độ trễ, trần ghi và tỉ lệ xáo trộn dữ liệu trước khi đối chiếu với kết quả chuẩn mực.
- **Kiểm chứng qua demo kit độc lập** — Khóa học cung cấp năm demo kit chạy trên nền Docker để bạn cùng coding agent dựng môi trường thực nghiệm, tái hiện lỗi và đo đạc số liệu trước và sau khi tối ưu.

## Khóa học dành cho ai

1. **Junior developer hoặc vibe coder** — Bạn đang vận hành app trên nền Postgres với sự hỗ trợ của AI agent, gặp tình trạng database quá tải hoặc đầy ổ đĩa, và cần kiến thức nền tảng chuẩn xác để đưa ra quyết định kiến trúc đúng đắn.
2. **Developer vừa nhận đề xuất sharding** — Bạn cần có số liệu thực tế để đánh giá xem hệ thống đã chạm trần ghi thật sự hay chưa, nên chọn cột nào làm shard key và khối lượng dữ liệu phải chuyển dịch là bao nhiêu trước khi bắt tay thực hiện.
3. **Kỹ sư đang vận hành cụm database nhiều shard** — Bạn đang đối mặt với các vấn đề vận hành hằng ngày như hot shard, truy vấn tán xạ phân tán chậm chạp, hoặc cần di dời dữ liệu giữa các server mà không làm gián đoạn dịch vụ.

## Những điều cần lưu ý

- **Kiến thức nền tảng cần chuẩn bị** — Bạn chỉ cần có kinh nghiệm làm việc với app thao tác dữ liệu qua transaction trong Postgres, đọc hiểu code TypeScript, SQL cơ bản và log hệ thống, không đòi hỏi kinh nghiệm quản trị hạ tầng phân tán từ trước.
- **Mối liên hệ với các chủ đề System Design khác** — Nội dung bài học tập trung vào bài toán định tuyến và phân vùng dữ liệu; các khái niệm mở rộng như outbox, fencing token, cơ chế đồng thuận hay failover cụm được kết nối tự nhiên với các chương trình chuyên đề tương ứng của 200Lab.
- **Định hướng về công nghệ và công cụ** — Khóa học không hướng dẫn cấu hình chi tiết cho một phần mềm cụ thể như Citus hay Vitess, mà tập trung làm rõ bản chất kiến trúc bên dưới để bạn hiểu sâu sắc những việc công cụ đang làm thay mình và tự tin chọn lựa giải pháp.
- **Tính chất của số liệu minh họa** — Mọi số liệu về dung lượng hay lưu lượng trong bài được thiết kế nhất quán để phục vụ việc tính toán logic; khi áp dụng vào thực tế, bạn sẽ dùng đúng phương pháp đó để đo đạc trên hệ thống của chính mình.

## Bắt đầu từ đâu

Khóa học bắt đầu bằng bài toán điển hình khi database đơn hàng chạm ngưỡng quá tải và agent đề xuất chia thành 8 shard theo hash của mã đơn. Lựa chọn này giúp lệnh ghi phân bổ đều nhưng lại khiến màn hình quản lý đơn của người bán chậm đi gần mười lần do phải truy vấn toàn bộ các server. Bài học mở đầu sẽ chỉ rõ vì sao truy vấn phân tán lại gây nghẽn hệ thống, cung cấp ba câu hỏi then chốt bạn cần số liệu trước khi phê duyệt đề xuất, và giới thiệu bậc thang mở rộng giúp bạn xác định chính xác vị trí hiện tại của database để chọn giải pháp phù hợp nhất.

## Chương trình

- Database không còn ghi kịp thì chia dữ liệu thế nào (miễn phí)

### Shard key, hot key và khi nào cần chia database

- Database sắp quá tải nhưng chưa chắc đã cần sharding (miễn phí)
- Partition khi một bảng quá lớn và sharding khi một máy không ghi kịp · quiz
- Chia database theo tháng làm mọi lệnh ghi dồn vào một shard · quiz · kit cho agent
- Vì sao một dòng đếm lượt xem làm chậm mọi trang sản phẩm? · quiz
- Tình huống: checkout treo khi hàng nghìn người cùng mua một SKU · kit cho agent

### Tìm đúng shard cho mỗi lệnh đọc và lệnh ghi

- Thêm database thứ năm có cần chép lại 80% dữ liệu không? · quiz
- Mỗi shard tự cấp mã đơn nên hai đơn hàng mang cùng một mã · quiz
- Tìm đơn theo số điện thoại nhưng phải hỏi mọi shard · quiz · kit cho agent
- Hai shop trên hai shard mà cùng đăng ký được một đường dẫn · quiz
- Tình huống: chia database đơn hàng ra hai shard trước đợt sale · kit cho agent

### Hot shard hoặc shard đầy thì chuyển dữ liệu thế nào

- Chuyển một bảng sang database mới khi app vẫn đang ghi · quiz
- Đã chuyển shard xong mà app vẫn ghi vào database cũ · quiz
- Vì sao chia theo hash mà một database vẫn đầy disk nhanh gấp đôi? · quiz
- Tình huống: chuyển kênh chat livestream sang database riêng · kit cho agent
