Case Study: Design Google Drive — File Storage & Sync System
“Google Drive nhìn như một thư mục bình thường trên máy tính. Nhưng đằng sau đó là một trong những hệ thống phức tạp nhất — đồng bộ file real-time giữa hàng triệu thiết bị, xử lý conflict, chunking, dedup, và đảm bảo không bao giờ mất dữ liệu.”
Tags: system-design case-study google-drive file-storage sync alex-xu Student: Hieu Prerequisite: Tuan-01-Scale-From-Zero-To-Millions · Tuan-02-Back-of-the-envelope · Tuan-03-Networking-DNS-CDN Liên quan: Tuan-08-Message-Queue · Tuan-15-Data-Security-Encryption · Tuan-07-Database-Sharding-Replication Reference: Alex Xu, System Design Interview Vol 1 — Chapter 15: Design Google Drive
Context & Why — Tại sao bài này quan trọng?
Analogy: Tủ hồ sơ chia sẻ trong công ty
Hieu, hãy tưởng tượng em làm việc trong một công ty lớn. Có một tủ hồ sơ trung tâm đặt ở phòng chung. Mọi nhân viên đều có thể:
- Bỏ tài liệu vào (upload)
- Lấy tài liệu ra xem (download)
- Ghi chú “chỉ cho anh A, chị B xem” trên bìa hồ sơ (sharing permissions)
- Nhìn thấy phiên bản cũ nếu ai đó sửa tài liệu (versioning)
Bây giờ, tưởng tượng tủ hồ sơ này có phép thuật: khi em sửa một tài liệu ở bàn làm việc, bản sửa tự động xuất hiện trong tủ trung tâm và trên bàn của mọi người được chia sẻ. Ngay lập tức. Không cần đi bộ tới tủ.
Đó chính xác là Google Drive, Dropbox, OneDrive — một distributed file storage and sync system.
Tại sao đây là bài toán kinh điển trong System Design Interview?
| Khía cạnh | Tại sao khó? |
|---|---|
| File chunking | File lớn phải chia nhỏ, upload song song, reassemble chính xác |
| Delta sync | Khi sửa 1 dòng trong file 100MB, không muốn upload lại toàn bộ 100MB |
| Conflict resolution | Hai người sửa cùng file cùng lúc — ai thắng? |
| Notification at scale | Một folder chia sẻ với 1000 người — khi file thay đổi, notify tất cả |
| Data durability | Mất file của user = mất niềm tin vĩnh viễn, yêu cầu 99.999999999% durability |
| Offline support | User sửa file khi không có mạng, sync lại khi có mạng |
| Storage cost | 50M users x 200 files x 500KB = petabytes of data, cần tối ưu chi phí |
Aha Moment: Google Drive không phải là bài toán “lưu file lên cloud”. Đó là bài toán distributed state synchronization — giữ trạng thái nhất quán của file trên N thiết bị, trong điều kiện mạng không ổn định, user hành xử không thể đoán trước.
Step 1 — Understand the Problem & Establish Design Scope
1.1 Clarifying Questions (Câu hỏi làm rõ)
Trong interview, luôn hỏi interviewer trước khi bắt tay vào thiết kế. Dưới đây là các câu hỏi quan trọng:
| Câu hỏi | Trả lời / Giả định | Tại sao quan trọng |
|---|---|---|
| Những feature chính cần hỗ trợ? | Upload, download, file sync, sharing, notifications | Xác định scope — không cần build Google Docs editor |
| Hỗ trợ những loại file nào? | Mọi loại file (documents, photos, videos, …) | Ảnh hưởng compression strategy |
| File cần encrypt không? | Có, cả at rest lẫn in transit | Security requirement |
| File size limit? | Tối đa 10GB per file | Ảnh hưởng chunking strategy |
| Số lượng users? | 50M registered, 10M DAU | Scale estimation |
| Cần sync across devices? | Có, real-time sync | Core feature, ảnh hưởng toàn bộ architecture |
| Cần file versioning? | Có, giữ lại lịch sử thay đổi | Storage và metadata impact |
| Cần offline editing? | Có, sync khi có mạng lại | Conflict resolution complexity |
| Cần sharing permissions? | Có (view, edit, owner) | ACL system design |
| Push notifications? | Có, khi file được chia sẻ/thay đổi | Notification service |
1.2 Functional Requirements (Yêu cầu chức năng)
- FR1: Upload file — hỗ trợ file lên đến 10GB, resumable upload
- FR2: Download file — tải file về thiết bị
- FR3: File sync — tự động đồng bộ file khi có thay đổi trên bất kỳ thiết bị nào
- FR4: File sharing — chia sẻ file/folder với người khác, phân quyền view/edit/owner
- FR5: Notifications — thông báo khi file được thay đổi, chia sẻ, hoặc comment
- FR6: File versioning — xem lịch sử thay đổi, rollback về phiên bản cũ
- FR7: Offline editing — cho phép chỉnh sửa file khi không có mạng
- FR8: Folder hierarchy — tổ chức file trong cấu trúc thư mục
1.3 Non-Functional Requirements (Yêu cầu phi chức năng)
| Yêu cầu | Mục tiêu | Giải thích |
|---|---|---|
| Reliability (Độ tin cậy) | Không mất dữ liệu, ever | 11 nines durability (99.999999999%) — giống S3 |
| Availability (Sẵn sàng) | 99.9% uptime | < 8.76 giờ downtime/năm |
| Scalability (Mở rộng) | 50M users, 10M DAU | Horizontal scaling cho mọi component |
| Performance | Upload: tối ưu bandwidth; Sync: < 5s cho small files | User experience cực kỳ quan trọng |
| Consistency | Eventual consistency cho sync, strong consistency cho metadata | Trade-off CAP theorem |
| Security | Encryption at rest + in transit, ACL | Bảo vệ dữ liệu user |
| Bandwidth efficiency | Delta sync, compression, dedup | Tiết kiệm bandwidth = tiết kiệm tiền + tốc độ nhanh hơn |
1.4 Capacity Estimation (Ước lượng năng lực)
Assumptions:
| Thông số | Giá trị | Giải thích |
|---|---|---|
| Registered users | 50M | Tổng user đăng ký |
| DAU | 10M | 20% registered users hoạt động hàng ngày |
| Avg files per user | 200 | Documents, photos, misc files |
| Avg file size | 500 KB | Nhiều document nhỏ, một số ảnh/video lớn |
| Storage per user | 100 MB (avg), 15 GB (limit) | Freemium model |
| Files synced per user per day | 5 | Trung bình 5 file thay đổi/ngày |
| Read:Write ratio | 2:1 | Users download nhiều hơn upload một chút |
Storage Estimation:
Note: Dedup giảm đáng kể vì nhiều user lưu cùng một file (meme, tài liệu công ty, template, …). Tỷ lệ dedup thực tế có thể lên đến 50–60%.
QPS Estimation cho Sync API:
Upload/Download QPS:
Bandwidth Estimation:
Metadata DB Size Estimation:
Aha Moment: Metadata DB chỉ khoảng 50 TB — hoàn toàn có thể xử lý bằng sharded relational DB. Nhưng file storage thì cần 15+ PB — đó là lý do phải dùng object storage (S3/GCS).
Step 2 — High-Level Design (Thiết kế tổng quan)
2.1 Các Component chính
Hieu, hệ thống Google Drive có thể chia thành các component lớn sau:
| Component | Vai trò | Tương tự trong analogy “tủ hồ sơ” |
|---|---|---|
| Client (Desktop/Mobile/Web) | Giao diện user, local cache, sync agent | Bàn làm việc của nhân viên |
| API Servers | Xử lý authentication, metadata operations, sharing | Nhân viên lễ tân tủ hồ sơ |
| Block Servers | Chia file thành blocks, xử lý upload/download blocks | Máy cắt giấy & máy ghép giấy |
| Cloud Storage (S3/GCS) | Lưu trữ file blocks thực tế | Tủ hồ sơ vật lý (rất rất lớn) |
| Metadata DB | Lưu thông tin file, user, versions, permissions | Sổ danh mục tủ hồ sơ |
| Metadata Cache (Redis) | Cache metadata thường xuyên truy cập | Danh mục “hay dùng” dán trên tường |
| Sync Service | Đồng bộ trạng thái file giữa các thiết bị | Người đưa tin báo cho mọi người biết tài liệu đã thay đổi |
| Notification Service | Push notifications tới users | Loa phóng thanh thông báo |
| Offline Queue | Hàng đợi cho các thay đổi offline | Hộp thư “chưa gửi” trên bàn |
| CDN | Phân phối file download cho user gần | Bản photocopy đặt sẵn ở mỗi tầng |
2.2 High-Level Architecture Diagram
flowchart TB subgraph "Client Layer" Desktop["Desktop Client<br/>(Windows/Mac/Linux)"] Mobile["Mobile Client<br/>(iOS/Android)"] Web["Web Browser"] end subgraph "Edge & Gateway" CDN["CDN<br/>(CloudFront / Akamai)"] LB["Load Balancer<br/>(ALB / Nginx)"] end subgraph "Application Layer" API["API Servers<br/>(Auth, Metadata, Sharing)"] BlockSrv["Block Servers<br/>(Chunking, Dedup,<br/>Compression)"] end subgraph "Sync & Notification" SyncSvc["Sync Service"] NotifSvc["Notification Service<br/>(Long Polling / WebSocket)"] MQ["Message Queue<br/>(Kafka / RabbitMQ)"] end subgraph "Storage Layer" S3["Cloud Storage<br/>(S3 / GCS)"] MetaDB["Metadata DB<br/>(MySQL / PostgreSQL<br/>Sharded)"] MetaCache["Metadata Cache<br/>(Redis Cluster)"] end Desktop & Mobile & Web --> LB Desktop & Mobile --> CDN LB --> API LB --> BlockSrv API --> MetaDB API --> MetaCache BlockSrv --> S3 API --> MQ MQ --> SyncSvc MQ --> NotifSvc SyncSvc --> MetaDB NotifSvc --> Desktop & Mobile & Web CDN --> S3
2.3 Luồng hoạt động tổng quan
Upload flow (tóm tắt):
- Client gửi file → Block Server chia thành blocks → Compress → Upload từng block lên Cloud Storage
- Block Server gửi metadata (block list, hash, size) → API Server → lưu vào Metadata DB
- API Server gửi event vào Message Queue → Sync Service + Notification Service
- Notification Service thông báo cho các thiết bị khác của user + người được chia sẻ
Download flow (tóm tắt):
- Client nhận notification “file changed” → gọi API Server lấy metadata mới
- API Server trả về block list (danh sách block hashes)
- Client kiểm tra local cache — chỉ download blocks mà client chưa có
- Download blocks từ CDN/Cloud Storage → Reassemble thành file hoàn chỉnh
Step 3 — Design Deep Dive
3.1 Block Server — Trái tim của hệ thống
3.1.1 File Chunking (Chia file thành blocks)
Tại sao phải chia file thành blocks thay vì upload nguyên file?
| Vấn đề khi upload nguyên file | Giải pháp bằng chunking |
|---|---|
| File 1GB upload fails ở 900MB → phải upload lại từ đầu | Mỗi block 4MB, fail ở block nào → retry block đó |
| Sửa 1 byte trong file 1GB → upload lại 1GB | Chỉ upload lại block bị thay đổi (delta sync) |
| Không thể upload song song | Upload nhiều blocks cùng lúc (parallel upload) |
| Không thể dedup | Hai file có chung 90% nội dung → 90% blocks giống nhau, chỉ lưu 1 lần |
Block size: Tại sao 4MB?
| Block size | Ưu điểm | Nhược điểm |
|---|---|---|
| 1 MB | Granularity cao, delta sync tiết kiệm hơn | Quá nhiều blocks → metadata overhead lớn |
| 4 MB | Cân bằng tốt giữa granularity và metadata overhead | — |
| 16 MB | Ít blocks → metadata nhỏ | Delta sync kém hiệu quả, retry tốn bandwidth |
| 64 MB | — | Một thay đổi nhỏ → upload 64MB, rất lãng phí |
Thực tế: Dropbox dùng block size 4MB. Google Drive dùng variable block size tuỳ theo loại file. Trong interview, chọn 4MB là an toàn.
3.1.2 Delta Sync (Đồng bộ chỉ phần thay đổi)
Delta sync là kỹ thuật chỉ upload/download những blocks đã thay đổi, thay vì toàn bộ file.
Cách hoạt động:
- File gốc được chia thành N blocks:
[B1, B2, B3, B4, ..., BN] - Mỗi block có hash (SHA-256):
[H1, H2, H3, H4, ..., HN] - User sửa file → Client chia file mới thành blocks → tính hash mới
- So sánh hash mới với hash cũ → chỉ những block có hash khác mới cần upload
- Upload blocks thay đổi → Server cập nhật block list trong metadata
Ví dụ thực tế:
| Scenario | Không có delta sync | Có delta sync | Tiết kiệm |
|---|---|---|---|
| Sửa 1 dòng trong file Word 20MB | Upload 20MB | Upload 4MB (1 block) | 80% |
| Thêm 1 slide vào PPT 50MB | Upload 50MB | Upload 4MB (1 block) | 92% |
| Sửa 1 cell trong Excel 8MB | Upload 8MB | Upload 4MB (1 block) | 50% |
| Thêm 100MB video vào folder | Upload 100MB | Upload 100MB (new file) | 0% |
Aha Moment: Delta sync tiết kiệm 90%+ bandwidth cho file editing use cases. Đây là lý do Dropbox thành công — trước Dropbox, hầu hết cloud storage upload lại toàn bộ file.
3.1.3 Compression (Nén dữ liệu)
Mỗi block được compress trước khi upload để tiết kiệm bandwidth và storage.
| Compression algorithm | Tốc độ | Tỷ lệ nén | Use case |
|---|---|---|---|
| gzip | Trung bình | Tốt (50–70% cho text) | General purpose, text files |
| lz4 | Rất nhanh | Trung bình (40–60%) | Real-time compression, khi tốc độ quan trọng hơn tỷ lệ nén |
| zstd (Zstandard) | Nhanh | Rất tốt (55–75%) | Best balance, Facebook phát triển |
| brotli | Chậm | Rất tốt (60–80%) | Static content, khi có thời gian compress |
Strategy: Compression không áp dụng cho file đã nén sẵn (JPEG, PNG, MP4, ZIP, …) vì sẽ không giảm được size mà còn tốn CPU. Block server kiểm tra MIME type hoặc thử compress một sample — nếu tỷ lệ nén < 5% thì skip.
3.1.4 Deduplication (Loại bỏ trùng lặp)
Hash-based dedup: trước khi lưu một block, tính hash (SHA-256) và kiểm tra trong Block Index (hash → storage location). Nếu hash đã tồn tại → không lưu block mới, chỉ tạo reference.
| Level | Mô tả | Ví dụ |
|---|---|---|
| File-level dedup | Nếu toàn bộ file có hash giống file đã lưu → skip upload | 1000 user upload cùng một bản PDF → lưu 1 lần |
| Block-level dedup | Nếu một block có hash giống block đã lưu → skip block đó | 2 file Word khác nhau nhưng có 80% nội dung giống → 80% blocks được dedup |
| Cross-user dedup | Dedup giữa các user khác nhau | Toàn công ty dùng chung template → chỉ lưu 1 bản |
Dedup flow:
- Client tính hash cho mỗi block (client-side dedup check)
- Client gửi danh sách hash tới Block Server: “Tôi muốn upload block có hash H1, H2, H3”
- Block Server kiểm tra Block Index: “H1 đã tồn tại, H3 đã tồn tại. Chỉ cần upload H2”
- Client chỉ upload block H2 → tiết kiệm 66% bandwidth trong ví dụ này
Aha Moment: Block-level dedup across users là lý do Dropbox có thể lưu trữ hiệu quả — khi triệu users upload cùng meme, presentation template, hoặc document, hệ thống chỉ lưu một bản duy nhất của mỗi block trùng lặp.
Lưu ý về hash collision: SHA-256 collision probability cực kỳ thấp ( cho birthday attack). Trong thực tế, xác suất hash collision thấp hơn xác suất hardware failure, nên an toàn để dùng hash-based dedup.
3.2 Cloud Storage — Nơi lưu trữ blocks
3.2.1 Tại sao dùng Object Storage (S3/GCS)?
| Tiêu chí | File System (EBS, NFS) | Object Storage (S3, GCS) |
|---|---|---|
| Scalability | Giới hạn bởi disk size, scale phức tạp | Gần như vô hạn, managed by cloud provider |
| Durability | Phụ thuộc RAID config, manual replication | 99.999999999% (11 nines) — tự động replicate |
| Cost | Đắt ($0.10/GB/month EBS) | Rẻ ($0.023/GB/month S3 Standard) |
| Access pattern | Low latency random read/write | High latency, tối ưu cho sequential read/write |
| Metadata | File system metadata (permissions, timestamps) | Custom metadata (key-value pairs) |
| Management | Phải tự quản lý, backup, scale | Fully managed |
Object storage phù hợp hoàn hảo vì file blocks là write-once, read-many — một khi block được upload, nó không bao giờ bị sửa (immutable). Khi file thay đổi, chỉ tạo blocks mới.
3.2.2 Data Durability — 11 Nines
Đạt được bằng cách:
- Replication across AZs: Mỗi object lưu ít nhất 3 bản ở 3 Availability Zones khác nhau
- Checksumming: Mỗi object có checksum, tự động detect và repair bit rot
- Versioning: Không bao giờ overwrite — luôn tạo version mới
3.2.3 Storage Tiers & Lifecycle Policies
| Storage Tier | Cost (approx) | Retrieval time | Use case trong Google Drive |
|---|---|---|---|
| S3 Standard | $0.023/GB/month | Milliseconds | Files được truy cập thường xuyên (recent files) |
| S3 Infrequent Access | $0.0125/GB/month | Milliseconds | Files không truy cập > 30 ngày |
| S3 Glacier Instant | $0.004/GB/month | Milliseconds | File versions cũ (> 90 ngày) |
| S3 Glacier Deep Archive | $0.00099/GB/month | 12–48 hours | Backup, versions rất cũ (> 1 năm) |
Lifecycle policy ví dụ:
| Tuổi của version | Storage tier | Chi phí relative |
|---|---|---|
| 0–30 ngày | Standard | 1x |
| 30–90 ngày | Infrequent Access | 0.54x |
| 90–365 ngày | Glacier Instant | 0.17x |
| > 365 ngày | Glacier Deep Archive | 0.04x |
Trong thực tế, phần lớn file versions là cũ và không bao giờ được truy cập lại, nên lifecycle policies tiết kiệm rất nhiều storage cost.
3.3 Metadata Database — Bộ não của hệ thống
Metadata DB lưu tất cả thông tin về files, users, sharing, versions — ngoại trừ nội dung file (nội dung nằm ở Cloud Storage).
3.3.1 Schema Design (Conceptual)
Table: users
| Column | Type | Mô tả |
|---|---|---|
| user_id | BIGINT PK | ID unique |
| VARCHAR | Email đăng nhập | |
| display_name | VARCHAR | Tên hiển thị |
| storage_used | BIGINT | Bytes đã dùng |
| storage_limit | BIGINT | Bytes tối đa (quota) |
| created_at | TIMESTAMP | Ngày tạo account |
Table: files
| Column | Type | Mô tả |
|---|---|---|
| file_id | BIGINT PK | ID unique |
| file_name | VARCHAR | Tên file |
| parent_folder_id | BIGINT FK | Folder chứa file (self-referencing) |
| owner_id | BIGINT FK → users | Chủ sở hữu |
| is_folder | BOOLEAN | True nếu là folder |
| latest_version_id | BIGINT FK → file_versions | Version mới nhất |
| file_size | BIGINT | Size tính bằng bytes |
| mime_type | VARCHAR | Loại file (application/pdf, image/png, …) |
| is_deleted | BOOLEAN | Soft delete (trash) |
| created_at | TIMESTAMP | Ngày tạo |
| updated_at | TIMESTAMP | Lần cuối cập nhật |
Table: file_versions
| Column | Type | Mô tả |
|---|---|---|
| version_id | BIGINT PK | ID unique |
| file_id | BIGINT FK → files | File nào |
| version_number | INT | Số thứ tự version |
| block_list | JSON / TEXT | Danh sách block hashes theo thứ tự |
| file_hash | VARCHAR | Hash toàn bộ file (cho dedup check) |
| file_size | BIGINT | Size của version này |
| modified_by | BIGINT FK → users | Ai sửa |
| created_at | TIMESTAMP | Thời điểm tạo version |
| change_description | VARCHAR | Mô tả thay đổi (optional) |
Table: blocks
| Column | Type | Mô tả |
|---|---|---|
| block_hash | VARCHAR PK | SHA-256 hash (cũng là key trong Cloud Storage) |
| block_size | INT | Size sau compression |
| storage_url | VARCHAR | URL/path trong Cloud Storage |
| reference_count | INT | Số file_versions tham chiếu tới block này |
| created_at | TIMESTAMP | Ngày upload |
Table: sharing_permissions (ACL)
| Column | Type | Mô tả |
|---|---|---|
| permission_id | BIGINT PK | ID unique |
| file_id | BIGINT FK → files | File/folder được chia sẻ |
| user_id | BIGINT FK → users | User được chia sẻ (nullable nếu link sharing) |
| permission_level | ENUM | ’owner’, ‘editor’, ‘viewer’ |
| shared_by | BIGINT FK → users | Ai chia sẻ |
| share_link_token | VARCHAR | Token cho link sharing (nullable) |
| link_expiry | TIMESTAMP | Thời hạn link (nullable) |
| created_at | TIMESTAMP | Ngày chia sẻ |
Table: device_sync_state
| Column | Type | Mô tả |
|---|---|---|
| device_id | VARCHAR PK | Device unique ID |
| user_id | BIGINT FK → users | Thuộc user nào |
| last_sync_cursor | BIGINT | Cursor/timestamp lần sync cuối |
| device_name | VARCHAR | ”Hieu’s MacBook Pro” |
| last_seen_at | TIMESTAMP | Lần cuối device online |
3.3.2 Folder Hierarchy — Cách lưu cấu trúc thư mục
Folder hierarchy được lưu bằng Adjacency List pattern: mỗi file/folder có parent_folder_id trỏ về folder cha.
| Phương pháp | Ưu điểm | Nhược điểm | Khi nào dùng |
|---|---|---|---|
| Adjacency List (parent_id) | Đơn giản, insert/move nhanh | Query “all descendants” cần recursive query | Google Drive — thường chỉ cần list immediate children |
| Materialized Path (“/root/folder1/folder2”) | Query descendants nhanh (LIKE ‘/root/folder1/%‘) | Move folder phải update path cho tất cả descendants | Khi query depth > 3 thường xuyên |
| Nested Set (left/right numbers) | Query subtree cực nhanh | Insert/move rất chậm (phải renumber) | Read-heavy, static hierarchy |
Chọn Adjacency List vì: (1) Operations chính là list immediate children, (2) Move/rename folder phải nhanh, (3) Recursive query cho “full path” có thể cache.
3.3.3 Database Selection & Sharding
Tại sao Relational DB (MySQL/PostgreSQL)?
- File metadata cần strong consistency — khi user upload file mới, tất cả devices phải thấy cùng metadata
- Relationships phức tạp: files ↔ versions ↔ blocks ↔ permissions ↔ users
- Transactions: update file + create new version phải atomic
- Mature tooling cho sharding, replication, backup
Sharding strategy: shard by user_id
| Shard key | Ưu điểm | Nhược điểm |
|---|---|---|
| user_id | Mọi query của 1 user nằm trên 1 shard; sharing query cần cross-shard nhưng hiếm | Hot users (nhiều file) tạo uneven distribution |
| file_id | Phân bố đều | List files of user cần scatter-gather across all shards |
Chọn user_id vì phần lớn operations là user-scoped (list my files, upload my file, get my file). Cross-shard query chỉ xảy ra khi xem shared files — có thể cache hoặc dùng separate sharing index.
Mỗi shard phục vụ ~500K users (50M / 100 shards), mỗi shard có 3 replicas (1 primary + 2 read replicas).
3.4 Sync Service — Đồng bộ giữa các thiết bị
Sync service là component phức tạp nhất trong toàn bộ hệ thống. Nó chịu trách nhiệm đảm bảo mọi thiết bị của user đều có cùng trạng thái file.
3.4.1 Sync Protocol
Mỗi thiết bị duy trì một sync cursor — một marker cho biết “tôi đã đồng bộ đến đâu”. Khi thiết bị reconnect hoặc nhận notification, nó gọi:
GET /api/v1/sync?cursor={last_sync_cursor}
Server trả về danh sách changes kể từ cursor đó:
| Field | Mô tả |
|---|---|
| file_id | File nào thay đổi |
| action | ’created’, ‘updated’, ‘deleted’, ‘moved’, ‘shared’ |
| new_metadata | Metadata mới (block list, name, parent, …) |
| version_id | Version mới |
| timestamp | Thời điểm thay đổi |
| new_cursor | Cursor mới cho lần sync tiếp |
3.4.2 Conflict Resolution — Phần khó nhất
Conflict xảy ra khi hai thiết bị sửa cùng một file cùng lúc (hoặc khi một thiết bị offline rồi sync lại).
Strategy 1: Last-Write-Wins (LWW)
| Aspect | Chi tiết |
|---|---|
| Cách hoạt động | Version nào có timestamp mới hơn → thắng |
| Ưu điểm | Đơn giản, automatic, không cần user intervention |
| Nhược điểm | Mất thay đổi của người thua — có thể gây mất dữ liệu |
| Ai dùng | Google Drive (cho binary files), iCloud |
Strategy 2: Manual Merge (Tạo conflict copy)
| Aspect | Chi tiết |
|---|---|
| Cách hoạt động | Khi detect conflict → tạo “conflict copy” với tên riêng, user tự quyết định |
| Ưu điểm | Không mất dữ liệu, user có toàn quyền quyết định |
| Nhược điểm | User phải xử lý manually, UX kém nếu conflict nhiều |
| Ai dùng | Dropbox, OneDrive |
Strategy 3: Operational Transform (OT) / CRDT
| Aspect | Chi tiết |
|---|---|
| Cách hoạt động | Merge changes ở mức operation level, tự động resolve |
| Ưu điểm | Real-time collaboration, không conflict |
| Nhược điểm | Cực kỳ phức tạp, chỉ áp dụng cho structured documents |
| Ai dùng | Google Docs (OT), Figma (CRDT) |
Trong Google Drive context, chọn combination approach:
- Structured documents (Google Docs, Sheets): OT — cho phép real-time collaboration
- Binary files (PDF, images, videos): Manual merge — tạo conflict copy
- Config/small files: Last-Write-Wins — đơn giản, ít risk
Aha Moment: Conflict resolution là phần khó nhất của file sync system. Không có giải pháp hoàn hảo — mỗi strategy có trade-off riêng. Trong interview, trình bày cả 3 strategies và giải thích khi nào dùng cái nào sẽ gây ấn tượng mạnh.
3.4.3 Conflict Resolution Flow
flowchart TD A["Client A & Client B<br/>cùng sửa File X"] --> B{"Server detect<br/>conflict?"} B -->|"Không (timestamps rõ ràng)"| C["Apply changes<br/>theo thứ tự thời gian"] B -->|"Có (concurrent edits)"| D{"Loại file?"} D -->|"Google Docs/Sheets"| E["Operational Transform<br/>Auto-merge operations"] E --> F["Cả hai thay đổi<br/>được giữ lại"] D -->|"Binary file<br/>(PDF, Image, ...)"| G["Tạo Conflict Copy"] G --> H["File X (từ Client A)<br/>File X (conflict copy - Client B)"] H --> I["Notify user:<br/>Vui lòng resolve conflict"] D -->|"Small config file"| J["Last-Write-Wins"] J --> K["Version mới nhất thắng<br/>Version cũ lưu trong history"] C --> L["Sync to all devices"] F --> L I --> L K --> L
3.5 Upload Flow — Chi tiết
sequenceDiagram participant C as Client participant API as API Server participant BS as Block Server participant S3 as Cloud Storage (S3) participant MDB as Metadata DB participant MQ as Message Queue participant NS as Notification Service Note over C,NS: === Phase 1: Chunking & Dedup Check (Client-side) === C->>C: Split file into 4MB blocks C->>C: Compute SHA-256 hash for each block C->>BS: Send block hash list for dedup check BS->>BS: Check Block Index BS-->>C: "Blocks H1, H3 already exist.<br/>Upload only H2, H4" Note over C,NS: === Phase 2: Upload Blocks === par Parallel Upload C->>BS: Upload Block H2 (compressed, encrypted) C->>BS: Upload Block H4 (compressed, encrypted) end BS->>S3: Store Block H2 BS->>S3: Store Block H4 S3-->>BS: Success + storage URLs Note over C,NS: === Phase 3: Update Metadata === BS->>API: Block upload complete (block list, hashes) API->>MDB: BEGIN TRANSACTION API->>MDB: INSERT new file_version (block_list = [H1,H2,H3,H4]) API->>MDB: UPDATE file (latest_version_id, updated_at) API->>MDB: UPDATE user (storage_used += file_size) API->>MDB: COMMIT MDB-->>API: Success Note over C,NS: === Phase 4: Notify === API->>MQ: Publish "file_updated" event MQ->>NS: Consume event NS->>C: Notify other devices of same user NS->>C: Notify shared users
3.5.1 Resumable Upload
Khi upload file lớn (hàng GB), mạng có thể bị ngắt giữa chừng. Resumable upload protocol:
- Initiate upload session: Client gọi API để tạo upload session, nhận
upload_session_id - Upload blocks: Mỗi block upload kèm
upload_session_id+block_index - Track progress: Server lưu danh sách blocks đã nhận trong session
- Resume on failure: Client hỏi “blocks nào đã upload thành công?” → chỉ upload blocks còn thiếu
- Complete upload: Khi tất cả blocks đã upload → finalize session → update metadata
| Tình huống | Không resumable | Có resumable |
|---|---|---|
| Upload 2GB file, mất mạng ở 1.8GB | Upload lại 2GB (100%) | Upload lại 200MB (10%) |
| Upload 500MB file qua mạng 3G yếu | Khả năng cao fail liên tục | Upload từng block 4MB, mỗi block có retry riêng |
3.5.2 Parallel Block Upload
Client chia file thành N blocks và upload đồng thời M blocks (M thường = 4–8, tuỳ bandwidth):
Ví dụ: File 100MB = 25 blocks x 4MB. Sequential upload trên mạng 10 Mbps mất ~80s. Parallel (M=4) mất ~20s.
3.6 Download Flow — Chi tiết
sequenceDiagram participant C as Client participant API as API Server participant MDB as Metadata DB participant Cache as Redis Cache participant CDN as CDN participant S3 as Cloud Storage Note over C,S3: === Phase 1: Get Metadata === C->>API: GET /api/v1/files/{file_id}/metadata API->>Cache: Check cache for file metadata alt Cache HIT Cache-->>API: File metadata (block list, version) else Cache MISS API->>MDB: SELECT file metadata + latest version MDB-->>API: Metadata API->>Cache: Cache metadata (TTL 5min) end API-->>C: File metadata + block_list [H1, H2, H3, H4] Note over C,S3: === Phase 2: Check Local Cache === C->>C: Compare block_list with local cache C->>C: "H1, H3 already in local cache.<br/>Need to download H2, H4" Note over C,S3: === Phase 3: Download Missing Blocks === par Parallel Download C->>CDN: Download Block H2 CDN->>S3: Fetch Block H2 (if not cached at edge) S3-->>CDN: Block H2 CDN-->>C: Block H2 C->>CDN: Download Block H4 CDN-->>C: Block H4 (cached at edge) end Note over C,S3: === Phase 4: Reassemble === C->>C: Decompress blocks C->>C: Verify block hashes (integrity check) C->>C: Reassemble: [H1, H2, H3, H4] → File C->>C: Update local sync cursor
Điểm quan trọng trong download flow:
| Optimisation | Mô tả | Impact |
|---|---|---|
| Local block cache | Client giữ blocks trong local cache → chỉ download blocks chưa có | Giảm 60–90% download traffic cho delta sync |
| CDN caching | Popular files được cache ở CDN edge gần user | Giảm latency, giảm load lên origin storage |
| Parallel download | Download nhiều blocks cùng lúc | 4–8x faster |
| Integrity verification | Verify hash sau download, retry nếu mismatch | Đảm bảo data integrity |
3.7 Notification Service — Thông báo thay đổi
Khi một file thay đổi, tất cả thiết bị của user + users được chia sẻ cần biết. Có 3 approach:
| Approach | Cách hoạt động | Latency | Resource usage | Khi nào dùng |
|---|---|---|---|---|
| Polling | Client hỏi server mỗi X giây “có gì mới không?” | Cao (phụ thuộc interval) | Cao (nhiều empty requests) | Không phù hợp cho file sync |
| Long Polling | Client mở connection, server giữ đến khi có event hoặc timeout | Trung bình (seconds) | Trung bình | Mobile clients, firewall-friendly |
| WebSocket | Persistent bidirectional connection | Thấp (real-time) | Thấp per-message, nhưng cần maintain connections | Desktop clients, web app |
Chọn approach: Kết hợp Long Polling (cho mobile, khi WebSocket khó maintain) + WebSocket (cho desktop client, web app).
3.7.1 Notification Scaling Challenge
Giả sử 1 folder được chia sẻ với 1000 users. Khi 1 file trong folder thay đổi:
- 1000 users cần được notify
- Mỗi user có trung bình 2 devices online
- → 2000 notification deliveries cho một lần file change
Giải pháp:
- Message Queue (Kafka) để decouple: file change event → Kafka → Notification Service consumers
- Notification Service scaled horizontally: mỗi instance quản lý N WebSocket/Long Polling connections
- Connection registry: Redis-based registry ánh xạ user_id → list of connected servers
- Batch notifications: Gộp nhiều changes vào 1 notification nếu chúng xảy ra gần nhau (debounce 1–2s)
3.8 File Versioning — Lịch sử thay đổi
3.8.1 Version Storage Strategy
Mỗi version không lưu toàn bộ file, mà lưu block list — danh sách hash của các blocks tạo thành version đó.
| Version | Block List | Blocks mới | Storage mới thực tế |
|---|---|---|---|
| v1 | [H1, H2, H3, H4] | H1, H2, H3, H4 | 16 MB (4 blocks x 4MB) |
| v2 | [H1, H2’, H3, H4] | H2’ | 4 MB (chỉ H2’ là mới) |
| v3 | [H1, H2’, H3, H4, H5] | H5 | 4 MB (chỉ H5 là mới) |
| v4 | [H1, H2”, H3’, H4, H5] | H2”, H3’ | 8 MB (2 blocks mới) |
3.8.2 Version Limits & Cleanup
| Policy | Mô tả | Lý do |
|---|---|---|
| Max versions per file | 100 versions | Giới hạn metadata growth |
| Version retention time | 30 ngày cho free tier, 365 ngày cho paid | Cost management |
| Old version storage tier | Glacier/Deep Archive | Cost optimization |
| Cleanup job | Background job xoá versions quá hạn, giảm block reference_count | Khi reference_count = 0 → xoá block khỏi Cloud Storage |
3.8.3 Rollback Flow
- User chọn “Restore version X” trong UI
- API Server lấy block_list của version X từ Metadata DB
- Tạo version mới (v_new) với cùng block_list như version X
- Không cần copy blocks — chỉ tạo metadata entry mới pointing to same blocks
- Tăng reference_count của các blocks liên quan
- Trigger sync → other devices download “new” version (thực tế là version cũ được restore)
Aha Moment: Rollback gần như instant vì không cần copy data — chỉ tạo metadata entry mới trỏ tới các blocks cũ. Đây là sức mạnh của content-addressable storage (block hash = block identity).
3.9 Offline Editing — Chỉnh sửa khi không có mạng
3.9.1 Local Cache Architecture
Desktop client duy trì:
| Component | Mô tả |
|---|---|
| Local file system | Files hiện tại, user thấy và edit trực tiếp |
| Block cache | Cache các blocks đã download, dùng cho delta sync |
| Local metadata DB | SQLite DB lưu file metadata, version info, sync state |
| Sync queue | Queue các pending changes chưa sync lên server |
| Conflict queue | Queue các conflicts chờ user resolve |
3.9.2 Offline Edit Flow
- User edits file offline → Client detect file change (file watcher / inotify)
- Client chia file mới thành blocks, tính hash → lưu vào local block cache
- Client tạo pending change entry trong sync queue:
- file_id, new block list, timestamp, action=‘updated’
- Khi có mạng lại → Client xử lý sync queue theo thứ tự FIFO:
- Gửi block hashes tới Block Server cho dedup check
- Upload blocks mới
- Update metadata
- Nếu conflict detected (server version đã thay đổi khi offline):
- Move change sang conflict queue
- Apply conflict resolution strategy (LWW hoặc tạo conflict copy)
- Notify user nếu cần manual resolution
3.9.3 Sync Queue Priority
| Priority | Action | Lý do |
|---|---|---|
| 1 (Highest) | Delete/move file | Ảnh hưởng folder structure, cần resolve trước |
| 2 | Create new file | User mong đợi file mới xuất hiện nhanh |
| 3 | Update existing file | Incremental change, ít urgent hơn |
| 4 | Metadata-only changes (rename) | Không ảnh hưởng content |
3.10 Scaling — Mở rộng hệ thống
| Component | Scaling Strategy | Chi tiết |
|---|---|---|
| API Servers | Horizontal scaling behind LB | Stateless, auto-scale based on CPU/request count |
| Block Servers | Horizontal scaling | Stateless — chỉ xử lý chunking/compression, không lưu state |
| Cloud Storage | Inherently distributed | S3/GCS tự scale, không cần quản lý |
| Metadata DB | Shard by user_id | 100+ shards, mỗi shard có read replicas |
| Metadata Cache | Redis Cluster | Sharded by key, replicated |
| Sync Service | Horizontal scaling + partitioned by user_id | Mỗi instance handle một subset of users |
| Notification Service | Horizontal scaling | Mỗi instance manage N WebSocket connections |
| Message Queue | Kafka với multiple partitions | Partition by user_id cho ordering guarantee |
| CDN | Managed by provider | CloudFront/Akamai tự scale toàn cầu |
Metadata DB Sharding Details:
500 GB per shard và 18 QPS per shard là rất thoải mái cho PostgreSQL/MySQL. Có thể bắt đầu với ít shards hơn và scale dần.
Block Storage Scaling: Cloud Storage (S3/GCS) là inherently distributed — provider tự xử lý replication, distribution, scaling. Đây là lợi thế lớn nhất khi dùng managed object storage: em không cần build distributed storage system.
Estimation Summary (Tổng hợp ước lượng)
| Metric | Giá trị | Ghi chú |
|---|---|---|
| Total users | 50M | Registered |
| DAU | 10M | 20% of total |
| Total files | 10 Billion | 50M x 200 files |
| Raw storage | 5 PB | Before replication & versioning |
| Effective storage (with dedup + versioning) | ~15 PB | After dedup, with versioning |
| Metadata DB size | ~50 TB | Sharded across 100+ shards |
| Sync QPS (peak) | ~1,737 req/s | |
| Upload QPS (peak) | ~693 req/s | |
| Download QPS (peak) | ~1,041 req/s | |
| Upload bandwidth (peak) | ~2.7 Gbps | |
| Download bandwidth (peak) | ~4.08 Gbps | |
| Notification fan-out (peak) | ~34,740 deliveries/s |
Security — Bảo mật
Encryption at Rest (Mã hoá dữ liệu lưu trữ)
| Strategy | Mô tả | Ưu điểm | Nhược điểm |
|---|---|---|---|
| Server-side encryption (SSE-S3) | Cloud provider tự encrypt/decrypt | Đơn giản, transparent | Provider có key → trust provider |
| SSE with Customer-Managed Key (SSE-CMK) | Dùng KMS, customer quản lý master key | Kiểm soát key rotation, revocation | Phức tạp hơn |
| Per-user key | Mỗi user có encryption key riêng, wrapped bằng master key | Revoke access nhanh (xoá key) | Key management phức tạp |
| Per-file key | Mỗi file có key riêng, wrapped bằng user key | Granular access control, sharing dễ (share file key) | Rất nhiều keys cần quản lý |
Recommended: Per-file key wrapped by per-user key, managed in KMS (Key Management Service).
Khi user A chia sẻ file với user B:
- Decrypt file key bằng user A’s key
- Re-encrypt file key bằng user B’s key
- Lưu encrypted file key cho user B
→ File data không bao giờ bị decrypt/re-encrypt — chỉ file key (nhỏ, nhanh).
Encryption in Transit (Mã hoá dữ liệu truyền tải)
| Layer | Protocol | Chi tiết |
|---|---|---|
| Client ↔ API Server | TLS 1.3 | HTTPS cho tất cả API calls |
| Client ↔ Block Server | TLS 1.3 | Block upload/download encrypted |
| Block Server ↔ Cloud Storage | TLS 1.3 (internal) | Trong cùng cloud provider, thường encrypted by default |
| Inter-service communication | mTLS | Mutual TLS giữa microservices |
Sharing Permissions & Access Control
| Permission Level | Capabilities | Ví dụ |
|---|---|---|
| Owner | Full control: read, write, delete, share, transfer ownership | Người tạo file |
| Editor | Read + write + comment | Đồng nghiệp cùng team |
| Commenter | Read + comment only | Reviewer |
| Viewer | Read only | Stakeholder xem báo cáo |
Link Sharing options:
| Setting | Mô tả |
|---|---|
| Anyone with the link | Bất kỳ ai có link đều truy cập được — thuận tiện nhưng rủi ro |
| Anyone in organization | Chỉ users trong cùng domain/org |
| Specific people | Chỉ users được invite explicitly |
| Link with expiry | Link tự hết hạn sau N ngày |
| Link with password | Cần nhập password mới truy cập |
| Disable download | Chỉ view online, không cho download |
Malware Scanning on Upload
Mỗi file upload đều được scan:
- Block Server nhận blocks → reassemble thành file tạm
- Gửi file tới Malware Scanning Service (ClamAV, hoặc cloud-native: S3 Malware Protection)
- Nếu clean → proceed với metadata update, notify users
- Nếu infected → quarantine file, notify owner, không chia sẻ với ai
Scanning có thể async — file được upload nhưng marked “scanning” trong metadata. Chỉ khi scan complete và clean mới cho phép download/share.
Data Loss Prevention (DLP)
| Measure | Mô tả |
|---|---|
| Content inspection | Scan file content cho sensitive data (SSN, credit card numbers, …) |
| Classification labels | Tự động gán label “Confidential”, “Internal”, “Public” |
| Sharing restrictions | Files classified “Confidential” không được share ngoài organization |
| Audit logging | Log mọi access, download, share action cho compliance |
| Watermarking | Thêm watermark vào documents khi download (enterprise feature) |
DevOps — Vận hành & Giám sát
Key Metrics to Monitor
Sync Performance
| Metric | Target | Alert threshold | Tại sao quan trọng |
|---|---|---|---|
| Sync latency (p50) | < 2s | > 5s | User experience — file phải xuất hiện nhanh |
| Sync latency (p99) | < 10s | > 30s | Tail latency ảnh hưởng heavy users |
| Sync success rate | > 99.9% | < 99.5% | Failed syncs = user mất dữ liệu (tạm thời) |
| Conflict rate | < 0.1% | > 1% | Conflict rate cao = UX problem |
| Sync queue depth | < 100 | > 1000 | Queue growing = system falling behind |
Upload/Download
| Metric | Target | Alert threshold |
|---|---|---|
| Upload success rate | > 99.5% | < 99% |
| Upload latency (p50) | < 3s (for 4MB block) | > 10s |
| Download success rate | > 99.9% | < 99.5% |
| Download latency (p50) | < 1s (for 4MB block) | > 5s |
| Resumable upload session completion rate | > 95% | < 90% |
Storage & Cost
| Metric | Monitoring purpose |
|---|---|
| Total storage used | Capacity planning |
| Storage growth rate | Predict khi nào cần scale |
| Dedup ratio | Hiệu quả dedup — thấp hơn expected → investigate |
| Cost per GB/month | Lifecycle policy có hoạt động đúng không |
| Cold storage migration rate | Bao nhiêu data đang di chuyển xuống tier thấp |
System Health
| Metric | Target |
|---|---|
| API Server response time (p99) | < 200ms |
| Metadata DB query latency (p99) | < 50ms |
| Message Queue lag | < 5s |
| WebSocket connection count | Track for capacity planning |
| Block Server CPU/memory | < 70% utilization |
Storage Cost Optimization
| Strategy | Savings estimate | Implementation |
|---|---|---|
| Lifecycle policies (move old versions to cold storage) | 40–60% | S3 lifecycle rules |
| Cross-user dedup | 30–50% | Block-level hash dedup |
| Compression | 20–40% (for text files) | gzip/zstd before upload |
| Delete orphaned blocks (reference_count = 0) | 5–10% | Background garbage collection job |
| Limit version count | 10–20% | Max 100 versions per file, TTL for versions |
Incident Response Playbook (Tóm tắt)
| Incident | Impact | Immediate action |
|---|---|---|
| Metadata DB shard down | Users trên shard đó không thể sync | Failover to read replica, promote to primary |
| Block Server overloaded | Upload/download slow | Auto-scale, rate limit heavy users |
| Sync service lag > 30s | Users thấy file cũ | Scale sync consumers, check Kafka lag |
| Cloud Storage outage | Mọi upload/download fail | Switch to backup region, serve from CDN cache |
| High conflict rate | User bị tạo conflict copies liên tục | Investigate — có thể do sync lag, tăng notification speed |
Mermaid Diagrams
Overall Architecture (Chi tiết)
flowchart TB subgraph "Clients" DC["Desktop Client<br/>• File watcher<br/>• Block cache<br/>• Sync queue<br/>• Local SQLite DB"] MC["Mobile Client<br/>• Selective sync<br/>• Thumbnail cache"] WC["Web Client<br/>• Browser-based<br/>• No local cache"] end subgraph "Edge" CDN["CDN<br/>(CloudFront)"] GLB["Global Load Balancer<br/>(DNS-based)"] end subgraph "Gateway" ALB["Application LB<br/>(ALB / Envoy)"] AUTH["Auth Service<br/>(OAuth 2.0 / JWT)"] end subgraph "Core Services" APIM["API Server — Metadata<br/>• File CRUD<br/>• Folder operations<br/>• Search"] APIS["API Server — Sharing<br/>• Permissions (ACL)<br/>• Link sharing"] BS["Block Server<br/>• Chunking (4MB)<br/>• Compression<br/>• Dedup check<br/>• Encryption"] end subgraph "Async Layer" KAFKA["Kafka<br/>(Event Bus)"] SYNC["Sync Service<br/>• Change detection<br/>• Conflict resolution<br/>• Cursor management"] NOTIF["Notification Service<br/>• WebSocket manager<br/>• Long Polling fallback<br/>• Push (FCM/APNs)"] SCAN["Malware Scanner<br/>• ClamAV<br/>• Async scanning"] end subgraph "Data Layer" MDB[("Metadata DB<br/>(PostgreSQL Sharded)<br/>• files, versions<br/>• users, permissions")] REDIS[("Redis Cluster<br/>• Metadata cache<br/>• Connection registry<br/>• Block index cache")] S3[("Cloud Storage (S3)<br/>• File blocks<br/>• 11 nines durability<br/>• Lifecycle tiers")] KMS["KMS<br/>(Key Management)"] end DC & MC & WC --> GLB DC & MC --> CDN GLB --> ALB ALB --> AUTH AUTH --> APIM & APIS & BS BS --> S3 BS --> REDIS APIM & APIS --> MDB APIM & APIS --> REDIS APIM --> KAFKA BS --> KAFKA KAFKA --> SYNC & NOTIF & SCAN SYNC --> MDB NOTIF --> DC & MC & WC CDN --> S3 BS --> KMS APIM --> KMS
Upload Flow với Block Server (Chi tiết)
flowchart TD A["Client: File changed<br/>(detected by file watcher)"] --> B["Split file into<br/>4MB blocks"] B --> C["Compute SHA-256<br/>hash per block"] C --> D["Send hash list<br/>to Block Server"] D --> E{"Block Server:<br/>Dedup check<br/>in Block Index"} E -->|"Block exists"| F["Skip upload<br/>(add reference)"] E -->|"Block is new"| G["Client uploads block"] G --> H["Block Server:<br/>Compress (gzip/zstd)"] H --> I["Block Server:<br/>Encrypt (AES-256)"] I --> J["Store in S3"] J --> K["Update Block Index<br/>(hash → storage URL)"] F --> L["All blocks processed?"] K --> L L -->|"No"| E L -->|"Yes"| M["API Server:<br/>Create new file_version<br/>(block_list, file_hash)"] M --> N["Update file metadata<br/>(latest_version, size, updated_at)"] N --> O["Publish event<br/>to Kafka"] O --> P["Sync Service:<br/>Update sync cursors"] O --> Q["Notification Service:<br/>Notify other devices<br/>& shared users"]
File Versioning Flow
flowchart LR subgraph "Version 1 (Original)" V1["v1: block_list =<br/>[H1, H2, H3, H4]"] end subgraph "Version 2 (Edit block 2)" V2["v2: block_list =<br/>[H1, H2', H3, H4]"] end subgraph "Version 3 (Add content)" V3["v3: block_list =<br/>[H1, H2', H3, H4, H5]"] end subgraph "Block Storage (S3)" BH1["Block H1<br/>ref_count=3"] BH2["Block H2<br/>ref_count=1"] BH2P["Block H2'<br/>ref_count=2"] BH3["Block H3<br/>ref_count=3"] BH4["Block H4<br/>ref_count=3"] BH5["Block H5<br/>ref_count=1"] end V1 --> BH1 & BH2 & BH3 & BH4 V2 --> BH1 & BH2P & BH3 & BH4 V3 --> BH1 & BH2P & BH3 & BH4 & BH5
Aha Moments & Pitfalls
Aha Moments — Những điểm sáng
| # | Insight | Chi tiết |
|---|---|---|
| 1 | Delta sync tiết kiệm 90%+ bandwidth | Thay vì upload/download toàn bộ file khi có thay đổi nhỏ, chỉ sync blocks thay đổi. Đây là breakthrough technology của Dropbox. |
| 2 | Block-level dedup across users | Khi triệu users lưu cùng file (meme, template, document phổ biến), hệ thống chỉ lưu một bản duy nhất của mỗi block. Tiết kiệm 30–50% storage ở scale lớn. |
| 3 | Versioning gần như miễn phí | Nhờ block-level storage, tạo version mới chỉ tốn storage cho blocks thay đổi. Rollback chỉ cần tạo metadata entry mới — không cần copy data. |
| 4 | Content-addressable storage | Dùng hash làm block identifier (thay vì generated ID) giúp dedup tự nhiên: cùng content → cùng hash → cùng block. Elegant và powerful. |
| 5 | Separation of metadata & content | Metadata DB (50 TB) vs Content storage (15 PB) có đặc tính hoàn toàn khác nhau → cần solution khác nhau. Relational DB cho metadata, Object Storage cho content. |
| 6 | Notification fan-out | Một file change trong shared folder có thể trigger hàng nghìn notifications. Cần Message Queue để decouple và scale independently. |
Pitfalls — Những bẫy thường gặp
| # | Pitfall | Giải thích | Cách tránh |
|---|---|---|---|
| 1 | Bỏ qua conflict resolution | Nhiều ứng viên quên rằng offline editing + concurrent editing tạo conflicts. Đây là phần khó nhất và quan trọng nhất. | Luôn đề cập conflict strategies (LWW, manual merge, OT) và trade-offs |
| 2 | Upload toàn bộ file thay vì blocks | Không chunking = không delta sync, không resumable upload, không dedup. Tệ về mọi mặt. | Block-level architecture là foundation |
| 3 | Dùng polling cho notifications | Polling 10M clients mỗi vài giây = hàng triệu empty requests. Cực kỳ lãng phí. | Long Polling hoặc WebSocket |
| 4 | Quên file versioning | ”Chỉ cần lưu file mới nhất” → user mất dữ liệu khi ai đó overwrite bằng version sai. | Block-level versioning, version history, rollback |
| 5 | Không tách metadata và content | Cố lưu file content trong relational DB → DB bloat, slow queries, expensive storage. | Object Storage cho content, Relational DB cho metadata |
| 6 | Thiếu resumable upload | File 5GB upload fail ở 4.9GB → phải upload lại từ đầu. User sẽ bỏ đi. | Upload session + block-level retry |
| 7 | Notification service không scale | Shared folder với 10K members → 1 file change triggers 10K notifications → service quá tải. | Kafka + horizontal scaling + batching/debouncing |
| 8 | Quên encryption | File storage mà không encrypt = trust provider 100%. Enterprise customers sẽ không chấp nhận. | Per-file key, encryption at rest + in transit |
Wrap Up — Step 4 trong Interview
Những điểm nên mention khi kết thúc
| Topic | Nói gì |
|---|---|
| Single point of failure | Metadata DB — cần sharding + replication. Block Server — stateless, dễ scale |
| Data integrity | Checksum ở mọi layer: client, block server, cloud storage. End-to-end verification |
| Global scale | Multi-region deployment, cross-region replication cho metadata, CDN cho content |
| Cost optimization | Storage tiers, dedup, compression — ở scale PB, mỗi % savings = hàng triệu USD/năm |
| Monitoring | Sync latency, conflict rate, upload success rate — operational excellence |
| Privacy & compliance | GDPR (right to deletion), data residency (EU data stays in EU) |
So sánh với hệ thống thực tế
| Feature | Google Drive | Dropbox | OneDrive |
|---|---|---|---|
| Sync protocol | Proprietary | Block-level delta sync | Differential sync |
| Storage backend | Google Colossus | AWS S3 (historically), Magic Pocket (now) | Azure Blob Storage |
| Conflict resolution | LWW + Docs uses OT | Conflict copy | LWW + conflict copy |
| Block size | Variable | 4 MB | Variable |
| Offline support | Full (desktop), Limited (mobile) | Full | Full (desktop) |
| Real-time collab | Google Docs/Sheets/Slides (OT) | Dropbox Paper | Office Online (OT) |
Internal Links — Liên kết nội bộ
| Link | Liên quan đến phần nào |
|---|---|
| Tuan-08-Message-Queue | Kafka/RabbitMQ dùng để decouple sync events và notification delivery |
| Tuan-15-Data-Security-Encryption | Encryption at rest (per-file key), encryption in transit (TLS), KMS |
| Tuan-07-Database-Sharding-Replication | Metadata DB sharding by user_id, read replicas cho high read throughput |
| Tuan-01-Scale-From-Zero-To-Millions | Horizontal scaling strategy cho mọi component |
| Tuan-02-Back-of-the-envelope | Capacity estimation methodology |
| Tuan-03-Networking-DNS-CDN | CDN cho file download, DNS-based global load balancing |
| Tuan-06-Cache-Strategy | Redis cache cho metadata, local block cache trên client |
| Tuan-10-Consistent-Hashing | Có thể dùng cho metadata DB sharding hoặc block distribution |
| Tuan-13-Monitoring-Observability | Sync latency monitoring, conflict rate, storage cost tracking |
| Tuan-14-AuthN-AuthZ-Security | OAuth 2.0 authentication, ACL-based authorization |
| Tuan-19-Design-Notification-System | Notification service architecture, WebSocket vs Long Polling |
“Google Drive dạy em rằng system design không chỉ là ‘lưu data ở đâu’ — mà là ‘làm sao giữ data consistent across millions of devices, with minimal bandwidth, maximum reliability, and graceful conflict handling.’ Đó là bản chất của distributed systems.”