All posts
Understanding Concurrency
backendconcurrency

Understanding Concurrency

Dung Tran H.'s avatarDung Tran H.
Table of Contents7 sections

Handling more requests isn't just about adding more CPU cores. It's about making better use of the time your CPU would otherwise spend waiting.

Số lượng CPU cores luôn là hữu hạn, trong khi số lượng request gửi đến hệ thống có thể tăng lên hàng trăm, hàng nghìn hoặc nhiều hơn trong cùng một thời điểm.

Nhưng một server backend bình thường vẫn có thể xử lý hàng nghìn request mỗi giây.

Vậy CPU đang làm điều gì để một vài nhân có thể "gánh" được khối lượng request lớn đến vậy?

Câu trả lời nằm ở một sự thật ít ai để ý: phần lớn thời gian xử lý một request không nằm ở CPU, mà nằm ở việc chờ đợi — chờ Database trả kết quả, chờ Redis phản hồi, chờ một API bên ngoài. Trong lúc một request đang chờ, CPU không hề rảnh — nó tranh thủ xử lý request khác.

Cơ chế đứng sau khả năng này chính là Concurrency. Bài viết này sẽ đi từ hành trình thực tế của một request để giải thích Concurrency là gì, vì sao request phải chờ, chờ ở đâu, và nó khác Parallelism ở điểm nào.


Một request thực sự đi qua những đâu?

Quan sát sơ đồ trên, nhiều người thường nghĩ rằng trong suốt quá trình xử lý request, CPU luôn bận rộn tính toán.

Thực tế lại hoàn toàn ngược lại.

Điều thú vị là CPU chỉ thực sự thực hiện tính toán trong vài mili giây (ví dụ: parse HTTP request, chạy business logic, serialize JSON...). Phần lớn thời gian còn lại, request chỉ đơn giản là đang chờ I/O (Input/Output).

I/O (Input/Output) là các thao tác mà ứng dụng phải giao tiếp với tài nguyên bên ngoài CPU, chẳng hạn như:

  • Đọc hoặc ghi dữ liệu từ Database.

  • Truy cập Redis để lấy dữ liệu cache.

  • Gọi REST API hoặc gRPC tới một dịch vụ khác.

  • Đọc hoặc ghi file trên S3 hoặc ổ đĩa.

  • Gửi email hoặc đợi phản hồi từ một dịch vụ bên thứ ba.

Ví dụ, một request có thể mất 250 ms để hoàn thành:

Công việc

Thời gian

Parse HTTP request

1 ms

Kiểm tra cache (Redis)

2 ms

Query Database

40 ms

Gọi External API

200 ms

Serialize JSON

2 ms

Tổng thời gian

245 ms

Trong gần 245 ms đó, CPU chỉ thực sự làm việc khoảng 5–10 ms. Hơn 95% thời gian, ứng dụng chỉ đang đợi các hệ thống bên ngoài phản hồi.

Đây chính là lý do Concurrency trở nên quan trọng. Thay vì để CPU ngồi chờ một request hoàn thành, hệ điều hành hoặc runtime sẽ chuyển CPU sang xử lý một request khác đang sẵn sàng chạy. Nhờ đó, nhiều request có thể cùng tiến triển trong cùng một khoảng thời gian, dù CPU không thực sự xử lý tất cả chúng cùng lúc. Đây chính là bản chất của Concurrency.


Trong lúc chờ, CPU làm gì?

Giả sử Request A đang đợi Database trả kết quả trong 40 ms.

Nếu CPU đứng yên chờ thì tài nguyên sẽ bị lãng phí. Thay vào đó, hệ điều hành sẽ chuyển CPU sang xử lý Request B. Khi Request B gọi Redis, CPU tiếp tục chuyển sang Request C. Đến khi Database trả kết quả cho Request A, CPU quay lại tiếp tục xử lý.

Đó chính là Concurrency.

Concurrency không có nghĩa là nhiều request đang chạy cùng lúc.

> Nó có nghĩa là nhiều request cùng tiến triển trong một khoảng thời gian.


Nếu có 1.000 request cùng đến thì sao?

Giả sử hệ thống gồm:

  • Application Load Balancer (ALB)

  • Web Server (Nginx, Apache...)

  • Worker / Thread Pool

  • Business Logic

  • RedisDatabase

Khi một HTTP request được gửi đến, nó không đi thẳng đến CPU. Thay vào đó, request sẽ đi qua nhiều lớp:

  1. ALB phân phối request đến một Web Server.

  2. Nếu Web Server chưa kịp nhận kết nối, kernel sẽ tạm giữ kết nối trong TCP Listen Queue.

  3. Web Server gọi accept() để nhận kết nối và chuyển request đến Worker / Thread Pool.

  4. Một Worker sẽ thực thi business logic, có thể truy cập Redis hoặc Database, rồi trả response về client.

Nếu tất cả Worker đều đang bận:

  • Các kết nối mới sẽ tiếp tục chờ trong TCP Listen Queue cho đến khi Web Server nhận chúng.

  • Sau khi được accept(), request vẫn có thể phải chờ một Worker rảnh để được xử lý.

  • Nếu hàng đợi đầy, kernel có thể từ chối các kết nối mới.

Điều này cho thấy không phải mọi request đều được ứng dụng xử lý ngay khi vừa đến. Trước khi được Web Server nhận, một request có thể phải đi qua nhiều lớp như Load Balancer, TCP Listen Queue và cơ chế điều phối của Web Server.

Chỉ sau khi request được accept() và giao cho ứng dụng xử lý, nó mới trở thành một in-flight request. Từ thời điểm này, khi request phải chờ Database, Redis hoặc các dịch vụ bên ngoài phản hồi, CPU sẽ không ngồi chờ mà chuyển sang xử lý các request khác đang sẵn sàng thực thi. Khả năng cho nhiều request cùng tiến triển trong quá trình xử lý chính là Concurrency


Concurrency là gì?

Concurrency là khả năng quản lý và xử lý nhiều tác vụ trong cùng một khoảng thời gian bằng cách luân phiên giữa chúng.

Trên CPU đơn nhân, tại một thời điểm chỉ có một tác vụ thực sự chạy. Nhờ Context Switching, CPU liên tục chuyển đổi giữa các request đang sẵn sàng thực thi.

Mục tiêu của Concurrency là:

  • Giảm thời gian CPU nhàn rỗi.

  • Tăng khả năng đáp ứng.

  • Tận dụng thời gian chờ I/O.


Parallelism là gì?

Nếu Concurrency giúp nhiều công việc cùng tiến triển thì Parallelism giúp nhiều công việc thực sự chạy cùng lúc. Điều này yêu cầu nhiều CPU Core hoặc nhiều đơn vị xử lý.

4 request đang thực sự được thực thi đồng thời.


So sánh nhanh

Tiêu chí

Concurrency

Parallelism

Bản chất

Điều phối, luân phiên giữa nhiều tác vụ

Thực thi nhiều tác vụ tại cùng một thời điểm

Cần nhiều CPU Core?

Không bắt buộc — chạy tốt trên 1 core nhờ context switching

Bắt buộc — cần ít nhất 2 core trở lên

Mục tiêu chính

Tăng khả năng đáp ứng, tránh CPU rảnh khi chờ I/O

Tăng tốc độ xử lý, rút ngắn thời gian hoàn thành

Phù hợp với

Tác vụ I/O-bound (chờ mạng, DB, disk...)

Tác vụ CPU-bound (tính toán nặng)

Lời kết

Concurrency và Parallelism thường đi cùng nhau nhưng giải quyết hai bài toán khác nhau.

  • Concurrency giúp hệ thống quản lý nhiều request hiệu quả hơn bằng cách tận dụng thời gian chờ I/O.

  • Parallelism tận dụng nhiều CPU Core để rút ngắn thời gian xử lý.

Hiểu rõ hai khái niệm này sẽ giúp bạn dễ dàng tiếp cận các chủ đề như Context Switching, Thread Pool, Event Loop, Async I/O và thiết kế hệ thống hiệu năng cao.