Blocking & Non-Blocking

Blocking và Non-blocking ở khắp mọi nơi

Table lock engines sinh ra nhằm giải quyết những vấn đề xung đột khi có 2 requests đến table cùng một thời điểm. Request đó có thể là (Create, Read, Update, Delete)
Cả 2 cùng đọc => Ok không có chuyện gì xảy ra
Cả 2 đều yêu cầu ghi => Chết
1 yêu cầu đọc, 1 yêu cầu ghi => Chết

Tại sao? Hiểu một cách nôm na thì dữ liệu cuối cùng được lưu xuống là các files, table thực chất là cách tổ trức một tập hợp của các files trên hệ thống(file system).

Nếu request đầu tiên mà là một “long transaction” thì nó sẽ lock tới khi nào transaction commit mới đến lượt request sau, khi đó request sau một là time-out do đợi quá lâu, hai là dead-lock xảy ra. Dead-lock được detect dựa vào các Dead-lock monitor được build-in trong các databases, cơ chế hoạt động của dead-lock monitors dựa vào blocking và locking structure.

Blocking là gì?
Là việc một thread thực hiện việc quản lý đọc ghi, thread sẽ blocked cho đến khi một vài dữ liệu là sẵn sàng cho việc đọc hoặc ghi. Đôi khi nó rơi vào tình trạng nhiều người thì ngồi không mà có người thì bù đầu, bởi vì các thread khác không thể làm gì cả cho đến khi mọi thứ sẵn sàng.

Blocking IO

Blocking là nguyên nhân chính của việt thắt cổ chai (bottlenecks), block hoặc dead-locks, đến năm 2005 thì các ngôn ngữ phía server-side đã khắc phục vấn đề này, database thì có tăng thêm row-lock, read commited, read uncommited, …

Non-Blocking 
Event loop các requests đến được quản lý bởi một single thread, trước khi xử lý nó lần lượt tạo ra cho mỗi request một event tương ứng và các event này được đăng ký một vài callback để đảm bảo khi request hoàn tất nó sẽ báo lại.
Non-blocking là rất quan trọng như đối với người dùng thì ứng dụng luôn mượt mà, đối với IO manager thì sẽ tuân thủ theo thứ tự ưu tiên từ đó cho phép ứng dụng được hay trì hoãn việc đọc ghi.

Event loop in Non-blocking

Liên tưởng tới điều gì?
Nếu bạn nào là một application developer thì có thể liên tưởng ngay tới MainThread (hay UI Thread) và các background threads của mình. Nơi mà các background thread thì hừng hực khí thế, trong khi UI Thread là điểm cuối cùng được ví như một cửa khẩu nơi các hàng hóa, xe cộ, người được tập kết trước khi thông quan thì ùn ứ

Có bạn đi làm 8 năm rồi hỏi threadpool vẫn mơ hồ nên mình lấy ví dụ như sau để các bạn dễ hình dung về threadpool: 
“Người ta không sợ khối lượng công việc nhiều, mà chỉ sợ đầu ra của sản phẩm”. Threadpool, là ứng vào câu nói này giống như việc nếu bạn có một đống hàng vài chục tấn cần phải nhập cảng bạn ko thể xuống hàng một mình, bạn quyết định thuê 7 anh công nhân (7 anh này chính là 7 threads) giúp bạn xuống hàng và nhập cảng tuy nhiên để thay nhau cho đỡ mệt chỉ 4 anh bốc tại 1 thời điểm và 3 anh đợi và chờ lúc vào thay nhưng tới khi xuất cảng thì thủ tục ở cảng lại quá nhiều, lượng người xếp hàng dài làm cho chúng ta bị tắc gọi là (Blocking IO).

Thread pool & Blocking IO

Bạn nào làm Web thì cũng hiểu, nếu là một hệ thống có vài chục nghìn người dùng, thường xuyên thực hiện các thao tác nghiệp vụ đòi hỏi phải đọc ghi vào database thì việc nhíu giữ lại vài giây thôi là tài nguyên server cạn kiệt rồi, mọi thứ phải giống như một vòng tuần hoàn đều và đều, ăn nhanh quá thì đau dạ dày, huyết áp cao thì nhồi máu cơ tim vỡ động mạch, mà chậm quá thì huyết áp thấp rồi thiếu máu lên não 🙂

Mình nhớ lần nhìn thấy dead-lock kinh khủng nhất là ở một nhà máy nơi có một hệ thống tracking toàn bộ hoạt động của các dây chuyền máy, mỗi ngày nhà máy sản xuất vài chục ngàn các mainboard điện tử các loại. Trên mỗi mainboard có tới vài trăm linh kiện và rồi rất nhiều nghiệp vụ phức tạp khác. Hệ thống Tracking kia phải collect toàn bộ các hoạt động của các máy từ việc máy lắp linh kiện gì, loại nào, lắp ở đâu, thời gian lắp, board đã đến công đoạn nào … toàn bộ các dữ liệu như vậy và phải real-time xử lý nữa. Thời điểm đó cũng mới triển khai nên dead-lock ngày nào cũng xảy ra cả.

dead-lock
Kết quả truy suất từ dead-lock monitoring

Về mặt thiết kế hệ thống người ta luôn mong muốn có thể tách riêng việc đọc và việc ghi, điều đó có nghĩa nếu bạn nào thiết kế API, thì nó phải đảm bảo API một là Read và 2 là Write, chứ không nên gộp cả vào. áp dụng tương tự cho function-based, Ở bài sau mình sẽ nói rõ hơn lý do tại sao cần làm như vậy

Bài này mình chỉ muốn chia sẻ với các bạn về những giới hạn của việc đọc ghi, và các cơ chế xử lý cũng như quản lý việc đọc ghi thông qua IO thôi.

Bạn nhớ Like/comment/Share/Follow Gravity Model page để đón đọc những bài mới nhé!

Y Hoang

#table locking
#CQRS
#Blocking
#non-blocking
#IOManager

Please follow and like us:

Leave a Reply

Your email address will not be published. Required fields are marked *