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.
Service Mesh (như Istio, Linkerd) là gì? Tại sao nó giải quyết tốt các bài toán về Service-to-Service Communication trong Kubernetes?
Service Mesh là một tầng cơ sở hạ tầng chuyên dụng, độc lập được thêm vào hệ thống để quản lý việc giao tiếp an toàn, tin cậy và nhanh chóng giữa các microservices.
- Cơ chế hoạt động (Sidecar Pattern): Service Mesh triển khai một proxy siêu nhẹ (như Envoy) chạy song song bên cạnh mỗi container ứng dụng (gọi là Sidecar Proxy). Mọi lưu lượng mạng đi vào và đi ra khỏi service đều được định tuyến qua sidecar này mà ứng dụng không hề hay biết.
- Các bài toán giải quyết được:
- Traffic Management: Cấu hình định tuyến thông minh, Canary Deployments, A/B Testing, tự động Retry khi lỗi, Circuit Breaking.
- Security: Tự động mã hóa toàn bộ dữ liệu truyền tải giữa các services bằng giao thức mTLS (mutual TLS) và quản lý chứng chỉ số mà không cần sửa đổi mã nguồn ứng dụng.
- Observability: Thu thập số liệu chi tiết (Metrics, Distributed Tracing, Logs) về hiệu năng mạng, tỷ lệ lỗi giữa các cuộc gọi dịch vụ một cách tập trung.
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.
Tại sao Lambda Expressions syntax lại đóng vai trò quan trọng khi phát triển ứng dụng LINQ chịu tải cao?
Trong phát triển dự án với LINQ, việc tối ưu hóa và quản lý tốt Lambda Expressions syntax là vô cùng quan trọng để đảm bảo tính ổn định và hiệu năng của hệ thống. Dưới đây là các khía cạnh kỹ thuật cốt lõi:
- Cơ chế hoạt động: Nắm vững vòng đời và cách thức hoạt động của
Lambda Expressions syntaxdưới runtime để tránh các lỗi logic phổ biến. - Best Practices: Áp dụng các mẫu thiết kế chuẩn, hạn chế tối đa tài nguyên dư thừa và sử dụng các thư viện hỗ trợ tối ưu.
- Khắc phục lỗi: Sử dụng công cụ giám sát (APM, Profiling, Logs) để theo dõi hành vi, phát hiện kịp thời các hiện tượng như rò rỉ bộ nhớ hoặc nghẽn luồng.
- Tối ưu hóa: Cấu hình các tham số hệ thống phù hợp với quy mô tải thực tế của ứng dụng.
Tại sao Assemblies structures lại đóng vai trò quan trọng khi phát triển ứng dụng .Net chịu tải cao?
Trong phát triển dự án với .Net, việc tối ưu hóa và quản lý tốt Assemblies structures là vô cùng quan trọng để đảm bảo tính ổn định và hiệu năng của hệ thống. Dưới đây là các khía cạnh kỹ thuật cốt lõi:
- Cơ chế hoạt động: Nắm vững vòng đời và cách thức hoạt động của
Assemblies structuresdưới runtime để tránh các lỗi logic phổ biến. - Best Practices: Áp dụng các mẫu thiết kế chuẩn, hạn chế tối đa tài nguyên dư thừa và sử dụng các thư viện hỗ trợ tối ưu.
- Khắc phục lỗi: Sử dụng công cụ giám sát (APM, Profiling, Logs) để theo dõi hành vi, phát hiện kịp thời các hiện tượng như rò rỉ bộ nhớ hoặc nghẽn luồng.
- Tối ưu hóa: Cấu hình các tham số hệ thống phù hợp với quy mô tải thực tế của ứng dụng.
Tại sao Ionic UI Components library lại đóng vai trò quan trọng khi phát triển ứng dụng Ionic chịu tải cao?
Trong phát triển dự án với Ionic, việc tối ưu hóa và quản lý tốt Ionic UI Components library là vô cùng quan trọng để đảm bảo tính ổn định và hiệu năng của hệ thống. Dưới đây là các khía cạnh kỹ thuật cốt lõi:
- Cơ chế hoạt động: Nắm vững vòng đời và cách thức hoạt động của
Ionic UI Components librarydưới runtime để tránh các lỗi logic phổ biến. - Best Practices: Áp dụng các mẫu thiết kế chuẩn, hạn chế tối đa tài nguyên dư thừa và sử dụng các thư viện hỗ trợ tối ưu.
- Khắc phục lỗi: Sử dụng công cụ giám sát (APM, Profiling, Logs) để theo dõi hành vi, phát hiện kịp thời các hiện tượng như rò rỉ bộ nhớ hoặc nghẽn luồng.
- Tối ưu hóa: Cấu hình các tham số hệ thống phù hợp với quy mô tải thực tế của ứng dụng.




