Thư Viện Câu Hỏi Phỏng Vấn
Tổng hợp các câu hỏi tuyển dụng thực tế theo nhiều cấp độ từ Entry đến Expert để bạn tự tin chinh phục nhà tuyển dụng.
Phân biệt sự khác nhau giữa Sao chép đồng bộ (Synchronous Replication) và Sao chép bất đồng bộ (Asynchronous Replication) trong cơ sở dữ liệu?
Sao chép dữ liệu (Replication) giúp tăng tính sẵn sàng và khả năng chịu lỗi của hệ thống CSDL bằng cách nhân bản dữ liệu từ Node Chính (Leader/Master) sang các Node Phụ (Follower/Replica):
- Synchronous Replication (Sao chép đồng bộ): Khi Leader nhận được yêu cầu ghi, nó ghi dữ liệu cục bộ và gửi dữ liệu đó sang toàn bộ các Followers. Leader sẽ chờ cho đến khi tất cả Followers phản hồi đã ghi thành công rồi mới phản hồi commit thành công cho client.
- Ưu điểm: Nhất quán dữ liệu tuyệt đối (Zero Data Loss). Nếu Leader bị sập, các Followers chắc chắn chứa dữ liệu mới nhất để thay thế.
- Nhược điểm: Tốc độ ghi bị chậm (bằng tốc độ của Follower chậm nhất) và nếu một Follower bị mất mạng, toàn bộ hệ thống sẽ bị treo ghi.
- Asynchronous Replication (Sao chép bất đồng bộ): Leader ghi dữ liệu cục bộ và phản hồi commit thành công ngay lập tức cho client. Việc chuyển dữ liệu sang các Followers được thực hiện ngầm (bất đồng bộ) sau đó.
- Ưu điểm: Tốc độ ghi cực nhanh, hệ thống vẫn hoạt động bình thường kể cả khi các Followers bị mất kết nối.
- Nhược điểm: Có nguy cơ mất dữ liệu (Data Loss) nếu Leader bị sập đột ngột trước khi kịp đồng bộ các thay đổi mới sang Followers.
Hãy giải thích thuật toán Token Bucket và Leaky Bucket dùng trong thiết kế hệ thống giới hạn tần suất yêu cầu (Rate Limiting)?
Cả hai đều là thuật toán kinh điển dùng để giới hạn số lượng request gửi lên hệ thống để chống tấn công DDoS và quá tải:
- Token Bucket (Thùng chứa Token):
- Cơ chế: Có một thùng chứa có dung lượng tối đa là B tokens. Các tokens được thêm vào thùng một cách tuần tự theo tỷ lệ r cố định mỗi giây. Khi một request gửi đến, nó cần tiêu thụ 1 token để được xử lý. Nếu thùng hết token, request bị từ chối.
- Đặc điểm: Cho phép xử lý các đợt lưu lượng truy cập tăng đột biến (burst of traffic) miễn là trong thùng vẫn còn đủ token dự trữ.
- Leaky Bucket (Thùng rò rỉ):
- Cơ chế: Có một thùng chứa nước có dung lượng tối đa là B (tượng trưng cho hàng đợi request). Các request đến giống như nước đổ vào thùng. Đáy thùng có một lỗ nhỏ rò rỉ nước ra ngoài với tốc độ r cố định không đổi để xử lý. Nếu thùng đầy nước, request mới sẽ bị tràn ra ngoài (bị từ chối).
- Đặc điểm: Khống chế tốc độ xử lý đầu ra luôn ở mức ổn định, mượt mà (smooth rate) bất kể tốc độ đầu vào có tăng đột biến như thế nào.
Mẫu thiết kế CQRS (Command Query Responsibility Segregation) kết hợp Event Sourcing hoạt động như thế nào? Ưu và nhược điểm là gì?
Hãy giải thích các chiến lược thu hồi bộ nhớ đệm (Cache Eviction Policies) phổ biến như LRU (Least Recently Used) và LFU (Least Frequently Used)?
Khi bộ nhớ đệm (Cache) bị đầy, hệ thống cần giải phóng không gian bằng cách loại bỏ các key cũ theo các chiến lược nhất định:
- LRU (Least Recently Used - Ít được sử dụng gần đây nhất): Loại bỏ phần tử đã lâu không được truy cập. Cơ chế hoạt động dựa trên thứ tự thời gian của lần truy cập cuối cùng. Mỗi lần một key được truy cập, nó sẽ được đưa lên đầu danh sách. Khi đầy, phần tử ở cuối danh sách (cũ nhất) sẽ bị xóa. Phù hợp cho đa số trường hợp vì dữ liệu vừa được truy cập có khả năng cao sẽ được truy cập lại.
- LFU (Least Frequently Used - Ít được sử dụng thường xuyên nhất): Loại bỏ phần tử có tần suất (số lần) truy cập thấp nhất trong một khoảng thời gian. Cơ chế này đếm số lần truy cập của từng key. Khi đầy, key có bộ đếm nhỏ nhất bị xóa.
- Khác biệt: LRU tập trung vào tính chất thời gian (recency), trong khi LFU tập trung vào độ phổ biến (frequency). LFU có thể gặp vấn đề nếu một key được truy cập rất nhiều lần trong quá khứ nhưng hiện tại không dùng nữa, nó vẫn chiếm chỗ trong cache do bộ đếm tích lũy quá cao (có thể giải quyết bằng cách áp dụng cơ chế suy giảm - aging).
Khái niệm Circuit Breaker Pattern trong thiết kế hệ thống phân tán là gì? Giải thích 3 trạng thái Closed, Open và Half-Open?
Circuit Breaker (Bộ ngắt mạch) là mẫu thiết kế ngăn chặn một service liên tục gửi request đến một service khác đang bị lỗi hoặc quá tải, giúp bảo vệ tài nguyên hệ thống không bị cạn kiệt (như nghẽn luồng) và ngăn sập dây chuyền (Cascading Failure).
- 3 Trạng thái hoạt động:
- Closed (Đóng): Trạng thái bình thường. Mọi request đều được cho phép đi qua. Circuit Breaker sẽ theo dõi tỷ lệ lỗi của các phản hồi. Nếu tỷ lệ lỗi vượt quá ngưỡng cấu hình (ví dụ: 50% request thất bại), nó sẽ chuyển sang trạng thái Open.
- Open (Mở): Trạng thái ngắt mạch. Mọi request gửi đến sẽ bị chặn ngay lập tức và trả về lỗi giả lập (fallback error/timeout) mà không cần gọi đến service đích, giúp service đích có thời gian phục hồi.
- Half-Open (Nửa mở): Sau một khoảng thời gian chờ cấu hình sẵn ở trạng thái Open, Circuit Breaker sẽ tự động chuyển sang Half-Open. Nó cho phép một số lượng nhỏ request thử nghiệm đi qua. Nếu các request này thành công 100%, hệ thống coi như đã phục hồi và chuyển lại về Closed. Nếu có bất kỳ request nào thất bại, nó lập tức quay về trạng thái Open.
Hãy giải thích tính chất nhất quán cuối cùng (Eventual Consistency) và sự khác biệt so với nhất quán mạnh (Strong Consistency)?
- Đặc điểm: Rần dễ lập trình, nhưng tốn nhiều thời gian xử lý và làm giảm tính sẵn sàng (Availability) khi có lỗi mạng.
- Đặc điểm: Tốc độ ghi cực nhanh, tính sẵn sàng cao. Thích hợp cho các hệ thống quy mô lớn như mạng xã hội (số lượt thích, bình luận hiển thị lệch vài giây không ảnh hưởng đến trải nghiệm người dùng).
SOA (Service-Oriented Architecture) là gì? So sánh sự khác nhau giữa kiến trúc SOA và kiến trúc Microservices?
SOA là kiến trúc hướng dịch vụ, chia hệ thống thành các dịch vụ độc lập giao tiếp với nhau qua mạng. Microservices được coi là sự tiến hóa và tối giản hóa của SOA:
- Phạm vi & Chia nhỏ: SOA tập trung vào việc tích hợp các ứng dụng doanh nghiệp lớn khác nhau (Enterprise Application Integration). Microservices tập trung vào việc chia nhỏ một ứng dụng đơn lẻ thành các dịch vụ siêu nhỏ hoạt động độc lập.
- Giao tiếp: SOA sử dụng một trục tích hợp dịch vụ trung tâm lớn (Enterprise Service Bus - ESB) chứa nhiều logic chuyển đổi định dạng phức tạp (như SOAP/XML). Microservices sử dụng cơ chế giao tiếp đơn giản, gọn nhẹ (như RESTful API / JSON, gRPC, Message Broker).
- Quản lý dữ liệu: Trong SOA, các dịch vụ có thể chia sẻ chung một cơ sở dữ liệu lớn. Trong Microservices, mỗi dịch vụ bắt buộc phải sở hữu cơ sở dữ liệu riêng của nó (Database-per-Service) để đảm bảo tính cô lập hoàn toàn.
Enterprise Service Bus (ESB) đóng vai trò gì trong kiến trúc SOA truyền thống và tại sao nó bị loại bỏ trong Microservices?
Trong kiến trúc SOA, ESB hoạt động như một hệ thống bưu điện trung tâm trung chuyển và điều phối toàn bộ thông tin liên lạc giữa các dịch vụ:
- Vai trò của ESB: Chuyển đổi định dạng dữ liệu (ví dụ: XML sang JSON), chuyển đổi giao thức (HTTP sang JMS), định tuyến tin nhắn thông minh và quản lý các giao dịch phức tạp.
- Lý do bị loại bỏ trong Microservices:
- Quá nhiều Business Logic tập trung: ESB vi phạm nguyên tắc "Smart endpoints and dumb pipes" (Điểm cuối thông minh, đường ống ngu ngốc). Việc đưa quá nhiều logic vào ESB biến nó thành một khối Monolith mới, khiến việc nâng cấp, thay đổi một dịch vụ đòi hỏi phải cấu hình lại ESB, gây chậm trễ.
- Single Point of Failure: ESB bị sập sẽ làm toàn bộ hệ thống tê liệt.
- Microservices thay thế bằng API Gateway (chỉ làm nhiệm vụ routing, rate limiting, authentication đơn giản) và để các dịch vụ tự xử lý dữ liệu của chúng.
Cơ chế vô hiệu hóa cache (Cache Invalidation) trong CDN hoạt động như thế nào? Phân biệt giữa Purge và Ban?
Khi dữ liệu tĩnh trên server gốc thay đổi trước khi thời gian hết hạn (TTL) của CDN kết thúc, ta cần vô hiệu hóa cache cũ tại các Edge Servers để người dùng nhận được file mới:
- Purge (Xóa): CDN sẽ xóa bỏ hoàn toàn file cũ khỏi bộ nhớ đệm của Edge Server ngay lập tức. Lần request tiếp theo của người dùng sẽ là Cache Miss, CDN phải quay lại server gốc kéo file mới về. Thích hợp khi biết chính xác URL của file vừa thay đổi.
- Ban (Cấm/Gắn thẻ): Thay vì xóa vật lý, CDN đánh dấu (invalidate) file cũ dựa trên các tiêu chí hoặc biểu thức chính quy (Regex) hoặc HTTP Tags (Cache-Tags). Khi người dùng request, CDN gửi một request gọn nhẹ (HEAD) kèm theo điều kiện (
If-Modified-Since) về server gốc để kiểm tra xem file thực sự đổi chưa. Nếu có, CDN mới kéo file mới về; nếu chưa, nó tiếp tục dùng file cũ. - So sánh: Purge nhanh và triệt để hơn nhưng có thể tạo tải đột biến (thực hiện kéo lại file lớn) lên server gốc. Ban linh hoạt hơn, cho phép xóa hàng loạt file có chung tiền tố.
Giải thích chỉ mục thứ cấp (Secondary Index) trong NoSQL Database và tại sao việc lạm dụng nó có thể làm giảm hiệu năng hệ thống?
NoSQL Database được tối ưu hóa cực cao cho việc truy cập dữ liệu dựa trên Khóa chính (Primary/Partition Key) để đạt tốc độ O(1):
- Secondary Index: Là chỉ mục được tạo trên các trường dữ liệu không phải khóa chính, cho phép truy vấn linh hoạt dựa trên các thuộc tính khác (ví dụ: tìm sản phẩm theo
categorythay vìproduct_id). - Tại sao lạm dụng làm giảm hiệu năng:
- Chi phí ghi lớn: Mỗi khi thêm/sửa/xóa một bản ghi, NoSQL phải cập nhật đồng thời chỉ mục thứ cấp. Đối với các hệ thống có tần suất ghi cao (write-heavy), ghi chỉ mục thứ cấp sẽ làm chậm thao tác ghi rõ rệt.
- Tác động phân tán (Scatter-Gather): Trong hệ thống phân tán (Sharded NoSQL), khóa chính dùng để xác định trực tiếp phân mảnh (shard) chứa dữ liệu. Nhưng chỉ mục thứ cấp thường không chứa thông tin phân mảnh. Khi truy vấn bằng chỉ mục thứ cấp, NoSQL phải gửi request đến tất cả các shards để tìm kiếm (quá trình Scatter-Gather) và gộp kết quả lại, làm tăng băng thông mạng và độ trễ truy vấn.
Deadlock là gì? Cần thỏa mãn 4 điều kiện Coffman nào để xảy ra Deadlock và làm thế nào để phòng tránh?
Deadlock (Bế tắc) là hiện tượng hai hoặc nhiều tiến trình/luồng bị treo vô hạn vì mỗi bên đều đang giữ một tài nguyên và chờ đợi để có được tài nguyên mà bên kia đang nắm giữ.
- 4 Điều kiện Coffman (phải xảy ra đồng thời):
- Mutual Exclusion (Loại trừ tương hỗ): Tài nguyên không thể chia sẻ, chỉ có một luồng được giữ tại một thời điểm.
- Hold and Wait (Giữ và Chờ): Luồng đang giữ tài nguyên đã cấp phát và tiếp tục yêu cầu thêm tài nguyên mới.
- No Preemption (Không cướp đoạt): Tài nguyên không thể bị thu hồi cưỡng chế từ luồng đang giữ nó.
- Circular Wait (Chờ đợi vòng tròn): Tồn tại một chuỗi vòng tròn các luồng, trong đó luồng này chờ tài nguyên của luồng tiếp theo.
- Cách phòng tránh: Chỉ cần phá vỡ ít nhất 1 trong 4 điều kiện trên. Phổ biến nhất là phá vỡ điều kiện Circular Wait bằng cách quy định thứ tự khóa cố định (Lock Ordering) cho toàn bộ hệ thống (ví dụ: Luôn khóa tài nguyên A trước rồi mới khóa tài nguyên B, không được làm ngược lại). Hoặc sử dụng cơ chế giới hạn thời gian chờ khóa (Lock Timeout) để giải phóng nếu chờ quá lâu.
Làm thế nào để thiết kế và triển khai một thành phần hệ thống giải quyết vấn đề Circuit Breakers trong chủ đề Microservices?
Khi thiết kế hệ thống ở quy mô lớn với Microservices, việc giải quyết bài toán Circuit Breakers yêu cầu kiến thức vững chắc về kiến trúc phân tán:
- Tính sẵn sàng (High Availability): Thiết kế dự phòng (Redundancy) và tự động chuyển vùng khi có lỗi xảy ra để tránh Single Point of Failure.
- Khả năng mở rộng (Scalability): Ưu tiên mở rộng theo chiều ngang (Scale Out) và sử dụng các cơ chế lưu trữ bất đồng bộ.
- Tính an toàn & giám sát: Thiết kế hệ thống bảo mật Zero-Trust kết hợp thu thập số liệu tập trung (Monitoring, Logging) để xử lý sự cố nhanh chóng.
Làm thế nào để thiết kế và triển khai một thành phần hệ thống giải quyết vấn đề ConfigMaps & Secrets trong chủ đề Kubernetes?
Khi thiết kế hệ thống ở quy mô lớn với Kubernetes, việc giải quyết bài toán ConfigMaps & Secrets yêu cầu kiến thức vững chắc về kiến trúc phân tán:
- Tính sẵn sàng (High Availability): Thiết kế dự phòng (Redundancy) và tự động chuyển vùng khi có lỗi xảy ra để tránh Single Point of Failure.
- Khả năng mở rộng (Scalability): Ưu tiên mở rộng theo chiều ngang (Scale Out) và sử dụng các cơ chế lưu trữ bất đồng bộ.
- Tính an toàn & giám sát: Thiết kế hệ thống bảo mật Zero-Trust kết hợp thu thập số liệu tập trung (Monitoring, Logging) để xử lý sự cố nhanh chóng.
Làm thế nào để thiết kế và triển khai một thành phần hệ thống giải quyết vấn đề Performance load testing trong chủ đề Software Testing?
Khi thiết kế hệ thống ở quy mô lớn với Software Testing, việc giải quyết bài toán Performance load testing yêu cầu kiến thức vững chắc về kiến trúc phân tán:
- Tính sẵn sàng (High Availability): Thiết kế dự phòng (Redundancy) và tự động chuyển vùng khi có lỗi xảy ra để tránh Single Point of Failure.
- Khả năng mở rộng (Scalability): Ưu tiên mở rộng theo chiều ngang (Scale Out) và sử dụng các cơ chế lưu trữ bất đồng bộ.
- Tính an toàn & giám sát: Thiết kế hệ thống bảo mật Zero-Trust kết hợp thu thập số liệu tập trung (Monitoring, Logging) để xử lý sự cố nhanh chóng.
Làm thế nào để thiết kế và triển khai một thành phần hệ thống giải quyết vấn đề API Versioning trong chủ đề API Design?
Khi thiết kế hệ thống ở quy mô lớn với API Design, việc giải quyết bài toán API Versioning yêu cầu kiến thức vững chắc về kiến trúc phân tán:
- Tính sẵn sàng (High Availability): Thiết kế dự phòng (Redundancy) và tự động chuyển vùng khi có lỗi xảy ra để tránh Single Point of Failure.
- Khả năng mở rộng (Scalability): Ưu tiên mở rộng theo chiều ngang (Scale Out) và sử dụng các cơ chế lưu trữ bất đồng bộ.
- Tính an toàn & giám sát: Thiết kế hệ thống bảo mật Zero-Trust kết hợp thu thập số liệu tập trung (Monitoring, Logging) để xử lý sự cố nhanh chóng.



.png)
.png)