Câu hỏi & gợi ý trả lời
Q1. Global Interpreter Lock (GIL) trong Python là gì và nó ảnh hưởng thế nào đến Concurrency?
GIL là mutex ngăn nhiều native threads cùng thực thi Python bytecodes cùng một lúc trong CPython. Điều này khiến multithreading trong Python không tận dụng được đa nhân CPU cho các tác vụ CPU-bound (như xử lý ảnh, tính toán số học). Tuy nhiên, với I/O-bound tasks (gọi API, đọc ghi database), multithreading hoặc asyncio vẫn mang lại hiệu quả cao vì GIL được giải phóng khi chờ I/O.
Q2. Sự khác biệt cơ bản giữa list và tuple trong Python là gì? Khi nào nên dùng loại nào?
List là kiểu dữ liệu mutable (có thể thêm, xóa, sửa phần tử), lưu trữ dạng dynamic array và tiêu tốn nhiều bộ nhớ hơn. Tuple là immutable (không thể thay đổi sau khi tạo), có kích thước cố định và hiệu năng cấp phát bộ nhớ nhanh hơn list. Nên dùng tuple cho dữ liệu cố định (constant, dictionary key, cấu trúc record) và dùng list khi cần tập hợp dữ liệu động.
Q3. Cơ chế quản lý bộ nhớ và Garbage Collection (GC) trong CPython hoạt động như thế nào?
CPython quản lý bộ nhớ chủ yếu thông qua Reference Counting: mỗi object có một biến đếm số lượng tham chiếu, khi đếm về 0 thì vùng nhớ được thu hồi ngay lập tức. Để xử lý bài toán tham chiếu vòng (Cyclic References) mà Reference Counting bỏ sót, Python sử dụng thêm Generational Garbage Collector (chia làm 3 thế hệ generation 0, 1, 2) chạy ngầm để quét và dọn dẹp theo chu kỳ.
Q4. Decorator trong Python hoạt động ra sao? Nêu một use case thực tế trong Backend.
Decorator là một design pattern cho phép bọc (wrap) một function hoặc class để mở rộng hành vi của nó mà không làm thay đổi source code gốc, hoạt động dựa trên tính chất first-class function của Python. Trong backend, decorator thường dùng để kiểm tra authentication/authorization (ví dụ `@login_required`), đo thời gian thực thi (logging/metrics), rate-limiting, hoặc đăng ký endpoint routing.
Q5. Generator là gì và khác gì so với Regular Function? Khi nào nên sử dụng yield?
Generator là function trả về một iterator thông qua từ khóa `yield` thay vì `return`. Điểm khác biệt là generator duy trì trạng thái thực thi và chỉ sinh giá trị theo cơ chế lazy evaluation khi được gọi (ví dụ qua hàm `next()`), giúp tiết kiệm RAM tối đa. Rất hữu ích khi cần xử lý dữ liệu lớn như streaming file gigabytes, parse log liên tục hoặc đọc batch records từ database.
Q6. Phân biệt WSGI và ASGI. Django và FastAPI thuộc nhóm nào?
WSGI (Web Server Gateway Interface) là chuẩn giao tiếp đồng bộ (synchronous), mỗi request chiếm dụng một thread/process (phù hợp với Flask, Django truyền thống). ASGI (Asynchronous Server Gateway Interface) là chuẩn mở rộng hỗ trợ cả synchronous và asynchronous, xử lý tốt WebSocket, SSE và hàng nghìn kết nối đồng thời với non-blocking I/O. Django 3+ hỗ trợ cả hai, trong khi FastAPI được xây dựng hoàn toàn native trên nền ASGI (Starlette/Uvicorn).
Q7. Khi nào nên dùng Multiprocessing, Multithreading và Asyncio trong Python?
Dùng `multiprocessing` cho các tác vụ CPU-bound để vượt qua rào cản GIL và chạy trên nhiều core vật lý. Dùng `asyncio` (single-thread, event loop) cho hệ thống có lượng I/O-bound requests cực lớn, non-blocking I/O đồng thời cao mà tốn ít overhead. Dùng `threading` cho các tác vụ I/O-bound truyền thống khi làm việc với các thư viện bên thứ ba chưa hỗ trợ native async/await.
Q8. N+1 Query Problem trong ORM (Django ORM, SQLAlchemy) là gì và cách khắc phục?
N+1 Query xảy ra khi code truy vấn 1 lần để lấy danh sách N bản ghi cha, sau đó trong vòng lặp lại tiếp tục thực hiện thêm N truy vấn con để lấy dữ liệu liên kết, gây nghẽn database. Trong Django ORM, khắc phục bằng cách dùng `select_related` (tạo SQL JOIN cho ForeignKey/OneToOne) hoặc `prefetch_related` (chạy 2 queries và kết hợp dữ liệu bằng Python cho ManyToMany/Reverse ForeignKey). Trong SQLAlchemy dùng `joinedload` hoặc `selectinload`.
Q9. Authentication bằng JWT (JSON Web Token) hoạt động như thế nào? Điểm yếu và cách mitigation là gì?
JWT gồm 3 phần: Header, Payload và Signature được ký bằng secret/private key; server xác thực stateless mà không cần truy vấn session trong DB. Điểm yếu lớn nhất là khó thu hồi (revoke) token trước hạn khi bị lộ trừ khi hết hạn (expire). Giải pháp là dùng Access Token có hạn ngắn (ví dụ 15 phút) kết hợp Refresh Token lưu trong database/Redis có cơ chế blacklist khi logout/đổi mật khẩu.
Q10. Celery đóng vai trò gì trong kiến trúc Python Backend và nó hoạt động cùng Message Broker như thế nào?
Celery là distributed task queue dùng để đẩy các tác vụ nặng (gửi email, xuất PDF, import CSV, gọi third-party API chậm) ra chạy ngầm (asynchronously) ngoài request-response lifecycle chính của web server. Web application đóng vai trò Producer gửi message chứa task parameters vào Message Broker (như Redis hoặc RabbitMQ), sau đó các Celery Worker độc lập đóng vai trò Consumer sẽ kéo task về thực thi và có thể lưu kết quả vào Result Backend.
Q11. Sự khác biệt giữa Deep Copy và Shallow Copy trong Python?
Shallow copy (`copy.copy`) tạo một đối tượng mới nhưng chỉ sao chép tham chiếu (reference) của các nested objects bên trong; thay đổi nested object ở bản copy sẽ ảnh hưởng đến bản gốc. Deep copy (`copy.deepcopy`) tạo một đối tượng mới và đệ quy sao chép toàn bộ các object con bên trong độc lập hoàn toàn, thay đổi ở bản copy không gây tác động phụ tới bản gốc.
Q12. Database Indexing hoạt động như thế nào và khi nào việc đánh Index làm giảm hiệu năng?
Index thường sử dụng cấu trúc B-Tree giúp tìm kiếm dữ liệu theo độ phức tạp O(log N) thay vì full table scan O(N). Tuy nhiên, đánh quá nhiều index sẽ làm giảm hiệu năng của các thao tác ghi dữ liệu (`INSERT`, `UPDATE`, `DELETE`) vì database phải cập nhật lại cấu trúc cây index tương ứng sau mỗi lần ghi, đồng thời làm tăng dung lượng lưu trữ trên đĩa.