Giới thiệu
Phát triển backend không chỉ đơn thuần là viết mã. Đó là việc đưa ra các quyết định kiến trúc đúng đắn để hệ thống của bạn có thể mở rộng, đáng tin cậy và dễ bảo trì. Tuy nhiên, nhiều nhà phát triển backend, đặc biệt là ở cấp độ mới bắt đầu đến trung cấp, thường nhầm lẫn giữa các thuật ngữ có vẻ tương tự nhưng có nghĩa rất khác nhau.
Bài viết này sẽ phân tích 15 khái niệm backend thường bị hiểu sai. Đối với mỗi cặp khái niệm, bạn sẽ tìm thấy định nghĩa, sự khác biệt và ví dụ thực tiễn liên quan đến backend.
1. API Gateway vs Load Balancer
API Gateway
API Gateway là một lớp quản lý lưu lượng truy cập API. Nó xử lý xác thực, điều hướng yêu cầu, giới hạn tần suất, phiên bản hóa và đôi khi là caching. Đây thường là điểm vào cho các yêu cầu từ phía client.
Load Balancer
Load Balancer là một lớp phân phối các yêu cầu đều cho nhiều máy chủ hoặc dịch vụ. Nó đảm bảo khả năng chịu lỗi, ngăn chặn quá tải và cải thiện tính khả dụng.
Tại sao điều này quan trọng?
Sử dụng API Gateway để kiểm soát và thực thi chính sách. Sử dụng Load Balancer để phân phối lưu lượng. Nhầm lẫn giữa chúng có thể dẫn đến các lỗ hổng bảo mật hoặc tắc nghẽn.
2. Authentication vs Authorization
Authentication
Authentication xác nhận danh tính của người dùng (bạn là ai?).
Authorization
Authorization cấp quyền dựa trên danh tính của người dùng (bạn có thể làm gì?).
Tại sao điều này quan trọng?
Trong bảo mật backend, các bước này được thực thi ở các giai đoạn khác nhau. Một JWT có thể xác thực người dùng, nhưng kiểm soát truy cập dựa trên vai trò (RBAC) xử lý phân quyền. Nhầm lẫn giữa hai khái niệm này có thể dẫn đến lỗ hổng tăng quyền.
3. Concurrency vs Parallelism
Concurrency
Concurrency là nhiều tác vụ tiến triển cùng một lúc về mặt khái niệm, thường được xen kẽ trên một lõi CPU.
Parallelism
Parallelism là nhiều tác vụ thực thi đồng thời về mặt vật lý trên nhiều lõi hoặc máy.
Tại sao điều này quan trọng?
Trong các hệ thống backend, concurrency thường gặp trong việc xử lý hàng ngàn yêu cầu I/O-bound (I/O không đồng bộ, vòng lặp sự kiện). Parallelism cần thiết cho các khối lượng công việc CPU-bound (xử lý theo lô, suy diễn ML).
4. Scalability vs Performance
Scalability
Scalability là khả năng của một hệ thống thích ứng với khối lượng công việc tăng lên bằng cách thêm tài nguyên.
Performance
Performance là cách hiệu quả mà hệ thống hoạt động dưới khối lượng công việc hiện tại.
Tại sao điều này quan trọng?
Một hệ thống có thể hoạt động tốt cho 100 người dùng nhưng không thể mở rộng lên 10,000. Kỹ sư backend cần thiết kế cho cả hai — tối ưu hóa truy vấn cơ sở dữ liệu cải thiện hiệu suất, trong khi thêm bản sao cải thiện khả năng mở rộng.
5. Framework vs Library
Framework
Framework kiểm soát luồng ứng dụng. Bạn triển khai các phần cụ thể, nhưng framework điều phối thực thi. Ví dụ: Django, Spring.
Library
Library là mã có thể tái sử dụng mà bạn gọi khi cần. Bạn kiểm soát luồng. Ví dụ: NumPy, Lodash.
Tại sao điều này quan trọng?
Trong phát triển backend, việc chọn một framework xác định kiến trúc của bạn. Một thư viện cung cấp tính linh hoạt nhưng ít cấu trúc hơn. Hiểu sai điều này có thể dẫn đến tổ chức dự án kém.
6. Cơ sở dữ liệu quan hệ vs Không quan hệ
Cơ sở dữ liệu quan hệ (SQL)
Dữ liệu có cấu trúc, lược đồ nghiêm ngặt, hỗ trợ giao dịch ACID. Ví dụ: PostgreSQL, MySQL.
Cơ sở dữ liệu không quan hệ (NoSQL)
Không có lược đồ, tối ưu hóa cho tính linh hoạt và khả năng mở rộng. Ví dụ: MongoDB, DynamoDB.
Tại sao điều này quan trọng?
Sử dụng SQL cho các giao dịch tài chính hoặc dữ liệu đã được chuẩn hóa. Sử dụng NoSQL cho dữ liệu không cấu trúc, có khối lượng lớn và linh hoạt (nhật ký, nguồn cấp xã hội). Lựa chọn sai có thể ảnh hưởng đến khả năng mở rộng và tính toàn vẹn của dữ liệu.
7. Process vs Thread
Process
Process là thực thi độc lập với bộ nhớ cách ly.
Thread
Thread là đơn vị thực thi nhẹ bên trong một process chia sẻ bộ nhớ.
Tại sao điều này quan trọng?
Trong các máy chủ backend, việc tạo quá nhiều process sẽ lãng phí bộ nhớ. Threads (hoặc coroutine không đồng bộ) cho phép concurrency hiệu quả. Lựa chọn sai ảnh hưởng đến thông lượng và việc sử dụng tài nguyên.
8. Caching vs Memoization
Caching
Caching là một cơ chế chung để lưu trữ các kết quả tốn kém để tái sử dụng. Có thể là cấp độ ứng dụng, phân tán (Redis) hoặc cấp độ trình duyệt.
Memoization
Memoization là tối ưu hóa cụ thể cho hàm lưu trữ kết quả của các cuộc gọi hàm cho các đầu vào nhất định.
Tại sao điều này quan trọng?
Caching backend giảm tải cho cơ sở dữ liệu. Memoization tối ưu hóa các cuộc gọi hàm lặp lại trong các dịch vụ nặng về logic. Cả hai đều cải thiện hiệu suất, nhưng áp dụng ở các lớp khác nhau.
9. Microservices vs Monolith
Microservices
Microservices là ứng dụng được chia thành các dịch vụ độc lập giao tiếp qua APIs.
Monolith
Monolith là logic ứng dụng được gói gọn trong một đơn vị triển khai duy nhất.
Tại sao điều này quan trọng?
Microservices mở rộng độc lập nhưng tăng độ phức tạp trong vận hành. Monolith đơn giản hơn nhưng khó mở rộng hơn. Việc lựa chọn phụ thuộc vào kích thước hệ thống, đội ngũ và sự phát triển trong tương lai.
10. Fail Fast vs Fail Safe
Fail Fast
Fail Fast phát hiện lỗi sớm và dừng thực thi ngay lập tức.
Fail Safe
Fail Safe tiếp tục hoạt động an toàn ngay cả khi một số thành phần gặp lỗi.
Tại sao điều này quan trọng?
Trong các API backend, việc fail fast giúp việc gỡ lỗi dễ dàng hơn (đầu vào không hợp lệ trả về 400 ngay lập tức). Fail Safe áp dụng trong các hệ thống phân tán nơi sự dư thừa đảm bảo tính khả dụng.
11. Idempotent Operations
Idempotency
Idempotency có nghĩa là các yêu cầu lặp lại tạo ra cùng một kết quả.
Tại sao điều này quan trọng?
Các API backend (PUT, DELETE) phải là idempotent để xử lý các lần thử lại mà không gây ra các khoản phí trùng lặp hoặc bản ghi trùng lặp. Các API thanh toán phụ thuộc vào bảo đảm này.
12. Composition vs Inheritance
Composition
Composition xây dựng các đối tượng bằng cách kết hợp hành vi từ nhiều đối tượng nhỏ hơn.
Inheritance
Inheritance mở rộng hành vi bằng cách kế thừa.
Tại sao điều này quan trọng?
Trong các dịch vụ backend, composition tránh các cấu trúc lớp sâu mà khó bảo trì. Ưu tiên composition cho tính linh hoạt trong các hệ thống đang phát triển.
13. Horizontal vs Vertical Scaling
Horizontal Scaling
Horizontal Scaling thêm nhiều máy chủ để xử lý tải.
Vertical Scaling
Vertical Scaling thêm nhiều CPU/RAM vào một máy chủ.
Tại sao điều này quan trọng?
Các backend dựa trên đám mây mở rộng theo chiều ngang bằng cách sử dụng Kubernetes. Vertical Scaling có giới hạn và gây ra điểm đơn của lỗi.
14. Kiến trúc Event-driven vs Message-driven
Event-driven
Event-driven là các hành động được kích hoạt bởi các sự kiện hệ thống (ví dụ: các chủ đề Kafka).
Message-driven
Message-driven là các thông điệp rõ ràng được gửi giữa các dịch vụ (ví dụ: RabbitMQ).
Tại sao điều này quan trọng?
Event-driven là tốt nhất cho các kiến trúc phản ứng. Message-driven phù hợp với giao tiếp yêu cầu-phản hồi. Sử dụng sai có thể ảnh hưởng đến độ trễ và độ tin cậy.
15. Mã hóa vs Băm
Mã hóa
Mã hóa là một chuyển đổi hai chiều có thể được giải mã bằng một khóa. Được sử dụng để bảo vệ dữ liệu trong quá trình truyền tải hoặc khi lưu trữ.
Băm
Băm là một chuyển đổi một chiều, không thể đảo ngược. Được sử dụng để lưu trữ mật khẩu và kiểm tra tính toàn vẹn.
Tại sao điều này quan trọng?
Lưu trữ mật khẩu bằng mã hóa là không an toàn. Sử dụng băm (có salt) cho các hệ thống xác thực. Mã hóa nên được dành cho việc truyền tải dữ liệu nhạy cảm.
Kết luận
Hiểu đúng những khái niệm backend này không chỉ là để vượt qua các cuộc phỏng vấn. Nó còn là để thiết kế hệ thống có khả năng mở rộng, giữ an toàn và hoạt động tốt trong các điều kiện thực tế. Là một nhà phát triển backend, sự rõ ràng về các thuật ngữ này giúp bạn có ngôn ngữ và độ chính xác để xây dựng các hệ thống bền vững.
Câu hỏi thường gặp
1. Tại sao việc hiểu rõ các khái niệm backend lại quan trọng?
Hiểu rõ các khái niệm này giúp bạn thiết kế hệ thống tốt hơn và đảm bảo an toàn và hiệu suất.
2. Có tài liệu nào hữu ích để tìm hiểu thêm không?
Bạn có thể tham khảo các khóa học trực tuyến về phát triển backend hoặc sách chuyên ngành để nâng cao kiến thức của mình.