Việc hiểu sâu cách Python vận hành bên dưới các cú pháp đơn giản là chìa khóa để phân biệt giữa một ứng viên biết viết code và một kỹ sư hiểu hệ thống. Bài viết này hệ thống lại những điểm mấu chốt mà các kỹ sư dày dạn kinh nghiệm thường dùng để 'đào sâu' trong các buổi phỏng vấn Backend.
Global Interpreter Lock (GIL) và Concurrency
Đây là chủ đề kinh điển. Người phỏng vấn sẽ hỏi bạn tại sao Python (đặc biệt là CPython) khó thực hiện đa luồng (multi-threading) thực sự cho các tác vụ CPU-bound.
GIL là một mutex cho phép chỉ một thread nắm giữ quyền kiểm soát Python interpreter tại một thời điểm, nhằm mục đích đơn giản hóa việc quản lý bộ nhớ (reference counting).
Để xử lý yêu cầu thực tế, bạn cần phân biệt khi nào dùng 'threading' (cho I/O-bound: network, database) và khi nào dùng 'multiprocessing' (cho CPU-bound: xử lý ảnh, tính toán) để tận dụng đa nhân CPU.
- Threading: Hiệu quả với các tác vụ đợi I/O (chờ phản hồi API, đọc ghi file).
- Multiprocessing: Vượt qua giới hạn của GIL bằng cách khởi tạo các process tách biệt, mỗi process có Python interpreter và memory space riêng.
- Asyncio: Mô hình non-blocking I/O hiện đại thay thế cho threading trong các service cần xử lý hàng nghìn kết nối đồng thời.
Cơ chế quản lý bộ nhớ: Garbage Collection & Reference Counting
Python quản lý bộ nhớ chủ yếu thông qua Reference Counting. Tuy nhiên, cơ chế này không giải quyết được vấn đề 'reference cycle' (hai object tham chiếu chéo nhau).
Đó là lúc 'Garbage Collector' (GC) của Python vào cuộc. Nó chạy định kỳ để quét các cycle và giải phóng vùng nhớ không còn khả năng truy cập.
Hiểu được điều này giúp bạn tránh được các lỗi 'memory leak' khi làm việc với các hệ thống backend chạy dài hạn (long-running services).
- Reference Counting: Tăng lên khi gán, giảm đi khi sử dụng del hoặc nằm ngoài scope.
- Generational GC: Python chia đối tượng thành 3 thế hệ (0, 1, 2) để tối ưu việc quét rác, thường quét thế hệ 0 thường xuyên hơn.
- Dấu hiệu cảnh báo: Nếu memory usage của service tăng liên tục mà không có sự đột biến về traffic, hãy kiểm tra các vòng lặp tham chiếu khép kín.
Context Managers và 'Magic Methods'
Không chỉ dùng 'with open(...)', một Backend Engineer chuyên nghiệp phải biết cách tự tạo Context Manager thông qua dunder methods `__enter__` và `__exit__`.
Điều này cực kỳ quan trọng khi bạn làm việc với database connections, locks hoặc file handles, nơi việc đảm bảo tài nguyên được đóng (close) là bắt buộc, kể cả khi có ngoại lệ (exception) xảy ra.
Nhà tuyển dụng sẽ đánh giá cao tư duy quản lý tài nguyên của bạn qua cách bạn sử dụng từ khóa 'with' một cách tối ưu.
- __enter__: Khởi tạo tài nguyên trước khi vào block code.
- __exit__: Xử lý dọn dẹp (cleanup) sau khi block code kết thúc, kể cả khi có lỗi.
- contextlib: Hướng dẫn sử dụng thư viện chuẩn này để biến một generator đơn giản thành Context Manager bằng decorator @contextmanager.
Kiến trúc Middleware và Request Lifecycle
Khi làm việc với các framework như Django hay FastAPI, bạn cần nắm rõ chu trình xử lý một request: từ khi đến server, qua các Middleware, đến Route Handler và ngược lại.
Middleware là nơi lý tưởng để đặt các logic cross-cutting (Authentication, Logging, Metrics, Compression) mà không làm ô nhiễm code xử lý nghiệp vụ tại Controller.
- Request Middleware: Chỉnh sửa request trước khi vào controller.
- Response Middleware: Chỉnh sửa response trước khi gửi về client (ví dụ: thêm header, log kết quả).
- Độ ưu tiên: Hiểu rõ thứ tự các middleware thực thi là chìa khóa để debug các lỗi liên quan đến session hoặc security.
Database Transactions & ACID
Backend luôn đi kèm database. Khái niệm Atomic trong ACID (Atomicity, Consistency, Isolation, Durability) là nền tảng để đảm bảo tính toàn vẹn dữ liệu.
Ví dụ phỏng vấn thực tế: Nếu service của bạn cần trừ tiền trong ví (Wallet) và ghi lịch sử giao dịch (Transaction History), bạn phải đảm bảo cả hai điều này cùng thành công hoặc cùng thất bại.
Sử dụng Transaction trong Python (ví dụ với SQLAlchemy hoặc Django ORM) giúp bạn gói gọn các câu lệnh SQL thành một đơn vị công việc duy nhất.
- Atomicity: 'Tất cả hoặc không gì cả'.
- Isolation Levels: Hiểu các mức độ như Read Committed, Repeatable Read để tránh lỗi phổ biến như Dirty Read hoặc Lost Update.
- Retry logic: Biết cách triển khai retry khi gặp deadlock trong database transaction.
Ghi nhớ nhanh
- Nắm vững sự khác biệt giữa GIL, Threading và Multiprocessing để tối ưu hiệu năng.
- Hiểu cơ chế quản lý bộ nhớ là bước đệm để viết hệ thống ổn định, không rò rỉ bộ nhớ.
- Tận dụng Pythonic way (Context Managers, Decorators) để làm sạch code và quản lý tài nguyên bền vững.
- Luôn ưu tiên tính toàn vẹn dữ liệu bằng cách nắm vững ACID và các Transaction isolation levels.
- Middleware là giải pháp tối ưu cho nhu cầu xử lý logic xuyên suốt hệ thống.