Mutex và kỹ thuật giải quyết vấn đề tranh chấp tài nguyên do Race condition gây ra

Mutex và kỹ thuật giải quyết vấn đề tranh chấp tài nguyên do Race condition gây ra

Tin ngắn hàng ngày dành cho bạn
  • Hôm nay tình cờ mình biết đến trang web notes.andymatuschak.org có cách ghi chú rất hay. Bấm vào liên kết nó mở ra một thẻ mới bên cạnh. Cứ thế bấm vào thì nó lại tiếp tục mở ra. Giống như các ngăn tài liệu vậy.

    Kiểu trình bày này vừa dễ theo dõi mà còn đúng như kiểu viết theo mạch cảm xúc luôn. Tiếc là không thấy tác giả nguồn mở dự án này. Không biết có cái nào tương tự không ta 🤔

    » Xem thêm
  • Bạn nhận thấy sự khác biệt gì trong bức ảnh này không 😁

    » Xem thêm
  • Instagram hôm nay vừa mới giới thiệu ứng dụng chỉnh sửa video dành cho người sáng tạo nội dung có tên là Edits. Tầm này là cạnh tranh trực tiếp với các ứng dụng phổ biến trên thị trường luôn. Cơ mà chắc phải một thời gian nữa vì ngó qua tính năng vẫn hết sức cơ bản, đủ dùng thôi.

    À nhân tiện khoe luôn mình "chơi" IG cũng hơn 10 năm rồi đấy. Mọi người ai có IG thì để lại tài khoản cho mình xem với nhé 🥳.

    IG của mình là hoaitx_

    » Xem thêm

Vấn đề

Trong lập trình đôi khi chúng ta phải đối mặt với trường hợp cần ngăn chặn một yêu cầu đang muốn truy cập vào một biến, tệp, hay một cấu trúc dữ liệu nào đó mà yêu cầu khác đang nắm giữ. Nếu để các yêu cầu có quyền truy cập đồng thời vào một tài nguyên, sửa đổi chúng thì nhiều khả năng gây ra nhiều vấn đề hoặc thậm chí là lỗi không hề mong muốn.

Trong môi trường cân bằng tải - tức là cố gắng tạo ra nhiều phiên bản máy chủ giống nhau để tăng khả năng chịu lỗi cũng như xử lý đồng thời nhiều yêu cầu cùng một lúc. Khi đó càng khó ngăn chặn việc tranh chấp tài nguyên hơn bởi vì mỗi máy chủ hoạt động độc lập, rất khó khăn để liên hệ chúng với nhau. Chưa kể đến vấn đề hiệu suất cũng như độ phức tạp khi muốn thiết lập một kênh liên lạc chung.

Vậy phải có cách nào để quản lý được tài nguyên dùng chung chứ? Đó là lúc cần biết đến một thuật ngữ có tên là Mutex. Vậy Mutex là gì? Áp dụng trong trường hợp nào?

Race condition là gì?

Race condition

Race condition xảy ra khi có hai hay nhiều yêu cầu có thể truy cập dữ liệu được chia sẻ và chúng cố gắng thay đổi nó cùng một lúc. Vì thuật toán lập lịch luồng có thể hoán đổi giữa các luồng bất kỳ lúc nào, nên bạn không biết thứ tự mà các luồng sẽ cố gắng truy cập vào dữ liệu được chia sẻ. Do đó, kết quả của sự thay đổi dữ liệu lại phụ thuộc vào thuật toán lập lịch luồng, tức là cả hai luồng đang "chạy đua" để truy cập/thay đổi dữ liệu.

Vì lẽ đó, Race condition có thể gây ra lỗi không mong muốn trong lập trình, cần phải tìm ra cách để giải quyết việc tranh chấp này. Hay chí ít là phải xác định được yêu cầu nào có quyền thao tác với dữ liệu, loại bỏ yêu cầu còn lại hoặc chờ cho yêu cầu trước đó hoàn thành. Đó là lí do Mutex ra đời.

Mutex là gì?

Mutex

Mutex - Mutual Exclusion hay còn gọi là "loại trừ lẫn nhau" được tạo ra nhằm ngăn chặn Race condition. Với mục tiêu một luồng không bao giờ được truy cập vào tài nguyên mà một luồng thực thi đang nắm giữ.

Tài nguyên được chia sẻ là một đối tượng dữ liệu, mà hai hoặc nhiều luồng đồng thời đang cố gắng sửa đổi. Thuật toán Mutex đảm bảo rằng nếu một quy trình đang chuẩn bị thao tác sửa đổi trên một đối tượng dữ liệu thì không một quy trình/luồng nào khác được phép truy cập hay sửa đổi cho đến khi nó hoàn tất và giải phóng đối tượng để các quy trình khác có thể tiếp tục.

Mutex sử dụng trong trường hợp nào?

Trong lập trình, Mutex được thể hiện tuỳ thuộc vào ngôn ngữ hay công cụ lập trình.

Node.js không có khái niệm rõ ràng về Mutex. Có thể nghe đâu đó Node.js chỉ có một luồng vậy thì trường hợp tranh chấp tài nguyên đâu có xảy ra? Thực tế đúng là Node.js chỉ có một luồng và luồng đó được sử dụng để xử lý mã JS, nhưng còn các tác vụ I/O đa số được thực hiện bởi các luồng song song hay còn gọi là Worker Pool có trong libuv, thế nên vẫn có khả năng tranh chấp tài nguyên xảy ra tại đây.

Một số thư viện hỗ trợ triển khai mutex như async-mutex, về cơ bản nó vận dụng các giải pháp đánh dấu một luồng đang truy cập tài nguyên để loại trừ lẫn nhau, sử dụng Promise để chờ đợi cho đến khi được giải phóng (resolve)... Mọi thứ hoạt động, có lẽ vấn đề đáng lo ngại nhất lúc này chỉ là hiệu suất, bởi vì yêu cầu sau phải đợi yêu cầu trước giải phóng tài nguyên. Nhưng hãy dừng lại một chút, đó là trong trường hợp chỉ có 1 máy chủ. Vậy trong trường hợp có nhiều máy chủ hoặc trong môi trường phân tán (distributed) thì làm sao để ngăn chặn tranh chấp?

Môi trường phân tán là môi trường "nhân bản" nhiều phiên bản máy chủ giống nhau, tài nguyên chia sẻ lúc này cũng có thể nằm trong các máy chủ khác nhau. Khi đó những thư viện hỗ trợ liên lạc nội bộ như async-mutex có lẽ không thể giải quyết mutex theo cách thông thường được nữa. Vì chúng không phải tạo ra để xử lý trong trường hợp phân tán.

Thực tế nếu ứng dụng chỉ cần 1 máy chủ thì không cần bận tâm đến trường hợp phân tán này nữa. Nhưng ai biết đâu một ngày nào đó nó phát triển vượt trội, việc nhân bản chúng lên để cân bằng tải là điều khó tránh khỏi. Dù sớm hay muộn đó vẫn là vấn đề cần phải biết cách giải quyết.

Có nhiều cách xử lý tranh chấp trong trường hợp phân tán. Mỗi cách thể hiện ra những ưu nhược điểm để cho từng trường hợp cụ thể. Cách đơn giản nhất là chỉ chạy một máy chủ tập trung xử lý nghiệp vụ liên quan đến tài nguyên chia sẻ. Mô hình này có thể được thể hiện qua việc dùng message queue hay stream... đầy những yêu cầu cần xử lý vào queue và xử lý chúng lần lượt. Dĩ nhiên rằng như thế sẽ không có việc xung đột ở đây nữa.

Nhưng không phải lúc nào cũng có thể xử lý tách biệt như vậy. Trong trường hợp đó cần tìm đến một giải pháp mới. Tận dụng tốc độ của redis để làm kênh trao đổi chẳng hạn. Về cơ bản cách này hoạt động dựa trên nguyên tắc tạo ra một khoá (key) lưu lại trong redis, luồng xử lý nào nhanh tay nắm được khoá sẽ có quyền truy cập vào tài nguyên trước. Sau khi toàn tất nó giải phóng khoá để nhường cho các luồng xử lý tiếp theo.

Bạn có thể tự triển khai một thuật toán Mutex cho riêng mình hoặc sử dụng thư viện có sẵn. warlock hay live-mutex là những ví dụ. Trong khi warlock sử dụng Redis để tạo mối liên kết giữa các dịch vụ thì live-mutex tự triển khai một hệ thống liên kết riêng, theo mô hình client-server. Nhìn chung những thư viện này có thể đáp ứng nhu cầu ở một mức độ nào đó. Trong một hệ thống thông tin, khả năng "tin cậy", "chịu lỗi" và phục hồi sau sự cố luôn là mối quan tâm hàng đầu.

Redis cũng có một sản phẩm có tên là Distributed Locks, mà họ triển khai thuật toán gọi là Redlock, theo mô hình sử dụng nhiều máy chủ redis tuân thủ 2 nguyên tắc "Safety" và "Liveness" cho mức độ tin cậy cao cùng khả năng chịu lỗi trong môi trường phân tán.

Ngoài ra mutex còn được thể hiện trong việc giải quyết xung đột dữ liệu ở các dịch vụ như là trong cơ sở dữ liệu. Nơi các khoá (locks) phát huy tác dụng. Sử dụng khoá để toàn quyền truy cập vào một bảng hay một hàng dữ liệu và ngăn các truy vấn khác đọc hoặc thay đổi dữ liệu. Có thể tận dụng cơ chế khoá này để giải quyết Race condition, nhưng tài nguyên bị khoá liên tục trong thời gian dài là không mấy hiệu quả, làm giảm hiệu suất hay thậm chí còn gây ra tình trạng deadlock. Khi đó cần phải cân bằng hoặc tìm ra một giải pháp khác sao cho phù hợp hơn.

Tổng kết

Trong lập trình đặc biệt là lập trình trên nhiều luồng xử lý dữ liệu đòi hỏi giải quyết vấn đề tranh chấp tài nguyên. Tranh chấp có thể xảy ra mọi lúc mọi nơi, từ trong một máy chủ hay trong môi trường phân tán. Mutex là một trong những giải pháp ngăn chặn vấn đề này. Tuỳ vào ngôn ngữ lập trình và công cụ sử dụng mà có cách triển khai thuật toán Mutex khác nhau. Có thể tự tạo ra một thuật toán Mutext cho riêng mình hoặc sử dụng thư viện có sẵn để tiết kiệm thời gian mà vẫn mang lại hiệu quả.

Cao cấp
Hello

5 bài học sâu sắc

Mỗi sản phẩm đi kèm với những câu chuyện. Thành công của người khác là nguồn cảm hứng cho nhiều người theo sau. 5 bài học rút ra được đã thay đổi con người tôi mãi mãi. Còn bạn? Hãy bấm vào ngay!

Mỗi sản phẩm đi kèm với những câu chuyện. Thành công của người khác là nguồn cảm hứng cho nhiều người theo sau. 5 bài học rút ra được đã thay đổi con người tôi mãi mãi. Còn bạn? Hãy bấm vào ngay!

Xem tất cả

Đăng ký nhận thông báo bài viết mới

hoặc
* Bản tin tổng hợp được gửi mỗi 1-2 tuần, huỷ bất cứ lúc nào.

Bình luận (0)

Nội dung bình luận...