Fail-safe và fail-fast

Bài gốc: http://javapapers.com/core-java/fail-fast-vs-fail-safe/

Hệ thống sẽ phản ứng thế nào khi có một thất bại (failure) đặc trưng xảy ra như một hệ thống fail-fast (thất bại nhanh) hay fail-fast (thất bại an toàn). Bài viết này để thảo luận liệu fail-fast hay fail-safe tốt hơn. Nó sẽ phải làm gì với Java.

Fail fast và fail safe – cái nào tốt hơn?

Tuy từ “fail safe” có vẻ tốt hơn, nhưng tôi có cảm giác fail-fast là tốt nhất. Fail-safe không an toàn. Fail safe không có nghĩa là vững mạnh. Chúng ta đang giữ, che giấu những khuyết điểm(defect) trong hệ thống. Sự bền vững của hệ thống fail-safe có thể không được lâu dài. Hệ thống fail-safe cần cho các trường hợp có tính sẵn sàng sử dụng cao. Khi một thất bại (failure) được phát hiện, cách thức làm việc khác sẽ được thay thế và tính sẵn sàng sử dụng của hệ thống vẫn được đảm bảo.

Fail-fast đưa ra các khuyết điểm của hệ thông khi nó bị phát hiện. Lỗi được công khai rộng rãi và hệ thống sẽ tắt. Công việc sẽ bị tắt nghẽn, nhưng chúng ta được cơ hội khắc phục lỗi. Chúng ta sửa lỗi và mang hệ thống trở lại và chạy ngon lành :D. Điều đó làm cho hệ thống thật sự mạnh mẽ, không che giấu tình trạng lỗi của hệ thống. Mặc dù kết quả làm cho tính sẵn sàng của hệ thống bị gián đoạn, qua được khoảng thời gian đó, kết quả là ta sẽ được một hệ thống mạnh mẽ. Fail-fast đảm bảo rằng chúng ta không lái một chiếc xe tào lao và tạo ra những vấn đề không thể phục hồi được. Đừng chờ đợi những thất bại (failures) trong hệ thống một cách tự nhiên, nhưng nó (failure) nên được thiết kế bằng cách mà khi trong trường hợp thật bại không mong muốn thì chương trình nên fail-fast.

Thử tưởng tượng một câu hỏi điên rồ (provoking – kích động), có phải fail-fast tốt hơn cho lò phản ứng hạt nhân? 

Xử lý ngoại lệ và fail-fast hay fail-safe

Xử lý ngoại lệ (exception handling) trong Java ép chúng ta thiết kế chương trình fail-safe. Thay vì vậy chúng ta nên sử dụng xử lý ngoại lệ để thất bại (fail) hợp lý và nhanh chóng. Ngoại lệ không nên được mang theo trong luồng chạy của chương trình quá lâu. Nguyên tắc vàng với xử lý ngoại lệ là throw (ném) sớm và catch(bắt) trễ. Khi chúng ta đụng ngoại lệ, nó (ngoại lệ) nên được thrown(ném) ra ngay lập tức. Chúng ta không nên catch(bắt) ngoại lệ trừ khi chúng ta chắc chắn biết sẽ làm gì với nó và hành động mà chúng ta bắt ngoại lệ, nó nên phủ định thất bại (failure).

Fail-safe and fail-fast java iterators

Java iterator cung cấp cho chúng ta interface để phân tách những phần tử trong tập hợp (collection) cơ sở. Khi chúng đang sử dụng iterator, tập hợp không nên bị thay đổi. Nếu nguyên tắc này không được tuân thủ và xảy ra trong môi trường đa luồng, chúng ta sẽ nhận được ngoại lệ ConcurrentModificationException.

Fail-fast iterators

Chúng ta cần nhớ 2 điểm chính về vấn đề này. Điểm thứ nhất là, hành vi này(fail-fast) không được đảm bảo. Phát hiện sự thay đổi trong tập hợp và phân tích tập hợp không kết thúc một cách đồng bộ. Sự thay đổi trên tập hợp có thể không gây chú ý trong các tình huống nhất đinh. Vì vậy trong lập trình, đây là hành vi không nên được tin cậy. Ví dụ về fail-fast iterators là ArrayList, Vector, HashSet.

Fail-safe iterators.

Điểm thứ hai là không phải tất cả tập hợp đều fail-fast. Nên cho dù tập hợp bị thay đổi, thì nó không ném ra ngoại lệ . Khi một iterator được tạo ra, hoặc là nó được tạo trực tiếp trên tập hợp, hoặc nó được tạo trên bản sao của tập hợp. Một ví dụ của fail-safe iterators là ConcurrentHashMap.

Tóm tắt: Đọc xong mà hông hiểu gì thì thông cảm giúp mình, dịch qua khó diễn tả ý tác giả quá :D. Mình giải thích để các bạn nắm hơn. 

Khi chương trình có lỗi hoặc chạy sai ý đồ (business) thì chúng ta thường có hai cách giải quyết, một là cho chương trình tiếp tục chạy (có thể ghi vết lại lỗi hoặc im luôn) được gọi là fail-safe (thật bại an toàn hay thất bại mà chương trình không tiêu), hai là sẽ cho chương trình tiêu ngay lúc phát hiện lỗi được gọi là fail-fast (thất bại nhanh). Theo ý tác giả thì fail-fast sẽ tốt hơn vì khi có lỗi chương trình sẽ dừng, chúng ta sẽ phát hiện được lỗi (tiềm ẩn) ở đâu, khắc phục triệt để và cho chương trình khởi động trở lại, chương trình về lâu dài sẽ có chất lượng hơn. Nhưng với những chương trình mà phải đảm bảo mở liên tục không được ngắt (availability) thì fail-safe là nên hơn, chúng ta sẽ bắt lỗi, ghi vết và cho chương trình tiếp tục chạy để bảo đảm không bị tắt nghẽn. Fail-safe và fail-safe ở trên mang tầm vĩ mô :))

Tầm nhỏ mô thì trong Java các bạn sẽ gặp fail-safe và fail-fast trong Java Iterator. Java có 2 loại iterator là fail-safe iterator và fail-fast iterator. Khi bạn đang sử dụng iterator nào mà nếu thay đổi tập hợp nó sẽ văng ra ngoại lệ ConcurrentModificationException thì đó là fail-fast iterator (có lỗi là chết liền), fail-fast iterator thì có ArrayList, Vector, HashSet v.v. Còn iterator mà khi thay đổi tập hợp thì chương trình vẫn hoạt động bình thường được gọi là fail-safe iterator,ConcurrentHashMap là fail-safe iterator.

Các bạn có thể tham khảo thêm 2 bài viết này để rõ hơn về fail-safe và fail-fast iterators.

http://javarevisited.blogspot.com/2012/02/fail-safe-vs-fail-fast-iterator-in-java.html

http://javahungry.blogspot.com/2014/04/fail-fast-iterator-vs-fail-safe-iterator-difference-with-example-in-java.html

Như các bạn thấy mình dịch khá tệ, dịch từng từ nên khó truyền đạt hết hàm ý của các giả. Mình chỉ cố gắng cung cấp nhiều nhất từ khóa có thể để mọi người tìm kiếm. Mình khuyên các bạn nên đọc bài gốc tiếng Anh.

Got something to say? Go for it!