Che dấu lỗi bằng sự dư thừa

Một phần của tài liệu Đề cương Hệ Phân Tán (Có đáp án) (Trang 27 - 46)

7. Tính nhất quán và sử dụng bản sao

8.3. Che dấu lỗi bằng sự dư thừa

Nếu một hệ thống được coi là có khả năng chịu lỗi, nó phải có khả năng che giấu những lỗi xảy ta với các tiến trình khác. Kỹ thuật chính để che giấu lỗi là sử dụng sự dư thừa. Có 3 loại có thể thực hiện được là: dư thừa về thông tin (information redundancy), dư thừa về thời gian (time redundancy) và dư thừa về vật lý (physical redundancy).

 Dư thừa thông tin: dùng một số bit dư thừa được thêm vào để cho phép phục hồi lại dữ liệu từ dữ liệu lỗi. Chẳng hạn Hamming code có thể được thêm vào dữ liệu được truyền đi để bù lại nhiễu trên đường truyền.

 Dư thừa thời gian (Time redundancy): một hành động được thực hiện, sau đó nếu cần thiết nó sẽ được thực hiện lại một lần nữa. Các giao dịch sử dụng phương pháp này. Nếu một giao dịch bị bỏ qua, nó có thể được thực hiện lại mà không có tổn hại gì. Dư thừa thời gian tỏ ra đặc biệt hữu ích khi lỗi là tạm thời hoặc không liên tục.

 Dư thừa vật lý (Physical redundancy): các tiến trình hoặc thiết bị dự phòng được thêm vào giúp cho hệ thống hoàn thiện để chống lại thiếu sót hoặc hoạt động sai chức năng của một số thiết bị, có thể được thực hiện dựa theo phần cứng hoặc phần mềm. Chẳng hạn các tiến trình dự phòng có thể được thêm vào hệ thống để đề phòng trường hợp nếu có một số nhỏ trong số chúng gặp vấn đề, hệ thống vẫn có thể hoạt động chính xác. Nói cách khác, bằng cách sao chép các tiến trình, có thể đạt được khả năng chịu lỗi cao.

Ở hình vẽ trên, tín hiệu sẽ đi qua A,B,C theo thứ tự. Nếu một trong 3 thiết bị đó bị lỗi, kết quả cuối cùng có thể không chính xác.

Trong hình b, mỗi thiết bị được sao chép lại thành 3 bản. Tín hiệu lúc này sẽ không chỉ đi qua thiết bị A mà đi qua 3 thiết bị A1, A2, A3 giống hệt thiết bị A. Các tín hiệu ra sẽ được đưa và các bộ chọn (voter)V1, V2, V3. Đó là các mạch điện có 3 đầu vào và 1 đầu ra. Mỗi mạch so sánh này sẽ so sánh 3 tín hiệu A1, A2, A3 nếu 2 trong 3 output qua 3 thiết bị trên là giống nhau thì sẽ lấy tín hiệu đó, cón nếu cả 3 tín hiệu khác nhau thì đầu ra sẽ không xác định. Thiết kế như vậy được gọi là dư thừa module bậc ba TMR (Triple Modular Redundancy).

Giả sử rằng thiết bị Az nào đó bị lỗi, vẫn còn 2 thiết bị khác hoạt động đúng và hệ thống vẫn là tin cậy. Về bản chất, việc Az bị lỗi là hoàn toàn được che giấu, vì vậy tín hiệu vào cho B1, B2, B vẫn chính xác như trường hợp Az không hề bị lỗi.

Trong trường hợp cả B3 và C1 cùng lỗi, tổn hại của nó đối với hệ thống cũng được che giấu tốt và hệ thống vẫn hoạt động bình thường.

Một điều nữa là tại sao tại mỗi module phải có tận 3 bộ chọn? Hiển nhiên là các bộ chọn này cũng là các thiết bị bình thường và cũng có khả năng xảy ra lỗi. Việc thiết kế 3 bộ chọn như vậy nhằm mục đích khi một thiết bị hỏng sẽ không ảnh hưởng đến sự hoạt động của hệ thống.

Mặc dù không phải mọi hệ phân tán có khả năng chịu lỗi đều sử dụng TMR nhưng kỹ thuật đó là rất phổ biến để cung cấp một cái nhìn rõ ràng về một hệ thống có khả năng chịu lỗi.

Phục hồi tiến trình

Ta sẽ tập trung vào cách thức tiến hành để có thể đạt được khả năng chịu lỗi trong hệ phân tán. Phần trên ta đưa ra cách thức ngăn chặn lỗi xảy ra, tiếp theo ta sẽ xem xét những vấn đề thiết kế chung của nhóm các tiến trình, và tìm hiểu thế nào là một nhóm có khả năng chịu lỗi và xem xét cách thức hoạt động khi một hoặc một vài tiến trình trong nhóm bị lỗi.

Thiết kế

Phương pháp chính để xây dựng một hệ thống tin cậy là tổ chức vài tiến trình giống hệt nhau vào một nhóm và cùng có khả năng nhận khi bản tin được gửi đến. Theo cách này, nếu một tiến trình trong nhóm lỗi, các tiến trình khác có thể thay thế và đưa ra kết quả đúng cho cả nhóm.

Nhóm các tiến trình có thể là động. Những nhóm mới có thể được tạo ra và các nhóm cũ có thể bị loại bỏ. Một tiến trình có thể tham gia hoặc ra khỏi một nhóm trong suốt quá trình hoạt động của hệ thống. Một tiến trình có thể là thành viên của vài nhóm trong cùng một thời điểm. Do đó cần có những cơ chế để quản lý nhóm và quản lý các thành viên trong nhóm.

Một tiến trình có thể tham gia vào một nhóm trong nhiều nhóm mà nó có mặt và trong trường hợp có nhiều nhóm cùng yêu cầu thực hiện một công việc nào đó, nó sẽ được tự do lựa chọn.

 Nhóm phẳng: tất cả các tiến trình là ngang bằng nhau. Không có tiến trình chủ và mọi quyết định đều được thực hiện dựa theo tập thể.

 Nhóm phân cấp (Hierarchical Group): có một tiến trình đóng vài trò điều phối và tất cả các tiến trình khác cùng tuân thủ. Trong mô hình này, khi một yêu cầu cho

một công việc nào đó được đưa đến, dù là yêu cầu của client bên ngoài hay của các tiến trình trong nhóm đó đều được gửi đến ttt diều phối. Tiến trình điều phối sau đó quyết định tiến trình nào trong nhóm thích hợp nhất để thực hiện và sẽ chuyển đến nó.

Mỗi loại trong mô hình trên đều có những ưu và nhược điểm của nó. Nhóm phẳng là cân đối, nếu một trong những tiến trình đó bị lỗi, cả nhóm chỉ đơn giản là bị thu hẹp lại, nhưng vẫn có thể tiếp tục hoạt động. Nhược điểm của tổ chức này là quá trình đưa ra quyết định khá phức tạp. Chẳng hạn để quyết định bất kỳ một điều gì, đều phải tiến hành lựa chọn ý kiến giữa tất cả thành viên trong nhóm, dẫn đến tăng thời gian trễ và tốn tài nguyên.

Kiến trúc phân tầng có những đặc điểm ngược lại. Mất đi tiến trình điều phối dẫn đến toàn bộ nhóm ngừng hoạt động nhưng khi tiến trình điều phối hoạt động nó có thể tự đưa ra quyết định mà không làm phiền đến các thành viên khác.

Nhân bản và che giấu lỗi

Nhóm các tiến trình là một phần trong giải pháp xây dựng hệ thống chịu lỗi. Nói cụ thể, có một nhóm các tiến trình giống hệt nhau cho phép chúng ta che giấu một hoặc nhiều tiến trình lỗi trong nhóm. Nói cách khác, chúng ta có thể sao chép các tiến trình và tổ chức chúng thành một nhóm nhằm thay thế một tiến trình đơn lẻ (dễ bị lỗi) bằng một nhóm (có khả năng chịu lỗi hơn). Có 2 cách để đạt được sự sao chép như vậy: giao thức

primary-based (primary-based protocols) hoặc các giao thức ghi bản sao (repilcated-write protocol).

Một vấn đề chính trong sử dụng nhóm các tiến trình để tăng tính chịu lỗi là cần có bao nhiêu bản sao của tiến trình thì đủ? Để đơn giản hóa, chúng ta chỉ quan tâm đến các hệ thống ghi bản sao (replicated-write system). Một hệ thống được gọi là chịu lỗi k (k-fault tolerance) nếu nó có thể hoạt động đúng với k tiến trình bị lỗi. Nếu có k tiến trình bị lỗi thì cần có k+1 tiến trình khác không bị lỗi để quá trình lựa chọn kết quả vẫn diễn ra chính xác.

Thoả thuận trong hệ thống gặp lỗi

Việc tổ chức các tiến trình giống nhau và cùng nhóm giúp tăng khả năng chịu lỗi. Nếu một client có thể đưa ra quyết định của nó theo cơ chế bỏ phiếu, nó vẫn có thể đưa ra quyết định đúng nếu k trong số 2k+1 tiến trình hoạt động sai (k+1 tiến trình còn lại vẫn hoạt động chính xác). Nói chung một vấn đề khó khăn đặt ra là khi chúng ta yêu cầu một nhóm các tiến trình đưa ra một sự thống nhất, chẳng hạn như lựa chọn ra một tiến trình điều phối, thực hiện một giao dịch, phân chia công việc cho các tiến trình trong nhóm ....

Nếu tất cả sự truyền thông và các tiến trình là hoàn hảo thì dễ dàng đạt được sự thống nhất như vậy, nhưng nếu chúng không hoàn hảo thì sẽ nảy sinh những vấn đề khó khăn.

Mục tiêu chung của thuật toán thoả thuận phân chia (distributed agreement algorithm) là có tất cả những tiến trình không lỗi đạt được sự đồng thuận trong một số vấn đề, và thực hiện sự đồng thuận ấy trong một số nhất định các bước. Trong thực tế, các giả thuyết khác nhau về hệ thống bên dưới (underlying system) yêu cầu các giải pháp khác nhau.

Turek và Shasha (1992) phân thành những trường hợp sau:

 Đồng bộ hay không đồng bộ: hệ thống đồng bộ khi các tiến trình cùng hoạt động trong chế độ lock-step, có nghĩa là với hằng số c thì nếu bất kỳ tiến trình nào thực hiện c+1 bước thì các tiến trình khác cũng đã thực hiện ít nhất 1 bước. Hệ thống không thực hiện đồng bộ gọi là hệ không đồng bộ.

 Độ trễ về truyền thông (Communication delay) là có giới hạn hay không? Độ trễ có giới hạn nếu và chỉ nếu chúng ta biết rằng mỗi bản tin được gửi đi với thời gian tối đa được xác định trước.

 Việc chuyển các bản tin là có trật tự hay không? Nói cách khác chúng ta phân biệt tình huống liệu các bản tin từ cùng một bên gửi có được nhận theo đúng thứ tự nó được gửi hay không, với tình huống không có cơ chế nào đảm bảo điều đó.

 Việc truyền các bản tin là đơn điểm (unicasting) hay đa điểm (multicasting).

Với các điều kiện trên, việc đạt được sự đồng thuận giữa các tiến trình xảy ra như trong hình vẽ dưới đây. Trong tất cả các trường hợp khác, không có bất kỳ giải pháp nào. Hầu hết các hệ phân tán trong thực tế đều giả sử rằng các tiến trình hoạt động không đồng bộ, các bản tin được truyền đơn điểm (unicast), và độ trễ có giới hạn. Do đó, chúng ta phải truyển các bản tin theo đúng thứ tự, giống như trong TCP.

Phát hiện lỗi

Muốn che giấu lỗi, trước tiên chúng ta phải phát hiện được chúng. Phát hiện lỗi là một trong phần quan trọng của tính chịu lỗi, các thành viên không lỗi phải có khả năng xác định những thành viên còn lại bị lỗi hay không. Có 2 phương pháp chính :

 Chủ động: tiến trình gửi bản tin dạng “còn sống không ?” (“are you alive?”) tới mỗi thành viên khác

 Thụ động: tiến trình chờ bản tin được gửi đến từ các tiến trình khác.

Phương pháp thụ động chỉ có ý nghĩa khi chắc chắn rằng có đầy đủ các kết nối giữa các tiến trình. Trong thực tế, thường sử dụng phương pháp chủ động.

Các lý thuyết về phát hiện lỗi đều sử dụng cơ chế time-out để kiểm tra xem liệu một tiến trình có bị lỗi không, nhưng phương pháp này sẽ đưa đến kết quả không chính xác trong hệ thống mạng không tin cậy.

Việc phát hiện lỗi cũng có thể thực hiện bằng cách trao đổi thông tin đều đặn với các tiến trình lân cận. Các tiến trình đều đặn thông báo các dịch vụ mà nó đang cung cấp nên mỗi tiến trình sẽ biết về mỗi tiến trình khác và có thể xác định một tiến trình có bị lỗi hay không.

Một vấn đề quan trọng khác là cần phân biệt được giữa các lỗi thuộc về hệ thống mạng với lỗi của các tiến trình. Một cách để xử lý vấn đề này là không để một tiến trình đơn lẻ tự ý quyết định tiến trình lân cận nó có lỗi hay không. Thay vào đó, khi một nút phát hiện một không gửi tin được đến một nút lân cận, nó sẽ yêu cầu các nút lân cận khác xác định xem liệu chúng có thể gửi tin đến nút đó không, sau đó sẽ thông báo kết quả đến nút này.

TRUYỀN THÔNG TIN CẬY Truyền thông client/server tin cậy.

Việc che giấu lỗi trong hệ phân tán tập trung vào trường hợp có tiến trình bị lỗi. Nhưng ta cũng phải xét đến trường hợp các giao tiếp bị lỗi. Thông thường, một kênh giao tiếp có thể gặp các lỗi: lỗi sụp đổ, lỗi bỏ sót, lỗi thời gian và lỗi tùy ý. Việc xây dựng một kênh truyền thông tập trung vào che giấu lỗi sụp đổ và lỗi tùy ý.

Truyền thông điểm – điểm.

Trong hệ phân tán, truyền thông điểm – điểm tin cậy được thiết lập bằng cách sử dụng các giao thức truyền tin cậy như TCP. TCP che giấu được lỗi bỏ sót bằng cách dùng cơ chế thông báo ACK và việc thực hiện truyền lại. Những lỗi này hoàn toàn trong suốt với client.

Tuy nhiên TCP không che giấu được lỗi sụp đổ. Khi xảy ra lỗi sụp đổ thì kết nối TCP sẽ bị hủy nên nếu muốn che giấu lỗi, hệ thống phải có khả năng tự động tạo một kết nối mới.

RPC khi xảy ra lỗi và cách khắc phục

Với hệ thống RPC, năm lớp lỗi có thể xảy ra là:

 Client không thể định vị được server: Nguyên nhân gây lỗi là do server và client dùng các phiên bản khác nhau hoặc do chính server bị lỗi. Khắc phục bằng cách sử dụng các ngoại lệ (exception) để bắt lỗi như ở ngôn ngữ java và điều khiển tín hiệu (signal handle) như ở ngôn ngữ C. Hạn chế của phương pháp này là không phải ngôn ngữ nào cũng hỗ trợ ngoại lệ hay điều khiển tín hiệu. Nếu tự viết một ngoại lệ hay điều khiển tín hiệu thì sẽ phá hủy tính trong suốt.

 Bị mất bản tin yêu cầu từ client gửi đến server: Đây là loại lỗi dễ xử lý nhất: hệ điều hành hay client stub kích hoạt một bộ đếm thời gian (timer) khi gửi đi một yêu cầu. Khi timer đã trở về giá trị 0 mà không nhận được bản tin phản hồi từ

server thì nó sẽ gửi lại yêu cầu đó. Nếu bên client nhận thấy có quá nhiều yêu cầu phải gửi lại thì nó sẽ xác nhận rằng server không hoạt động và sẽ quay lại thành kiểu lỗi “không định vị được server”

 Server bị lỗi ngay sau khi nhận được yêu cầu từ client: Lúc này lại phân chia thành hai loại:

Loại 1: Sau khi thực hiện xong yêu cầu nhận được thì server bị lỗi.

Phương pháp khắc phục: sau đó server sẽ gửi thông báo hỏng cho client

Loại 2: Vừa nhận được yêu cầu từ client server đã bị lỗi ngay. Phương pháp khắc phục: client chỉ cần truyền lại yêu cầu cho. Vấn đề đặt ra lúc này là client không thể nói cho server biết yêu cầu nào là yêu cầu được gửi lại.

Khi gặp lỗi kiểu này, ở phía máy server sẽ thực hiện theo 3 kĩ thuật sau:

 Đợi đến khi nào server hoạt động trở lại, nó sẽ cố thực hiện yêu cầu đã nhận được trước khi lỗi đó. Như thế RPC thực hiện ít nhất một lần.

 Server sau khi được khôi phục nó sẽ không thực hiện yêu cầu nhận được trước khi bị lỗi mà sẽ gửi lại thông báo hỏng cho client biết để client gửi lại yêu cầu. Với kĩ thuật này thì RPC thực hiện nhiều lần nhất.

 Không thực hiện gì để đảm bảo cả. Khi server bị lỗi, client không hề hay biết gì cả. Kiểu này, RPC có thể được thực hiện nhiều lần cũng có thể không thực hiện lần nào.

Còn ở client thì có thể thực hiện theo 4 chiến lược sau:

 Client không thực hiện gửi lại các yêu cầu. Vì thế không biết bao giờ yêu cầu đó mới thực hiện được hoặc có thể không bao giờ được thực hiện.

 Client liên tục gửi lại yêu cầu: có thể dẫn tới trường hợp một yêu cầu được thực hiện nhiều lần.

 Client chỉ gửi lại yêu cầu nào đó khi không nhận được bản tin ACK phản hồi từ server thông báo đã nhận thành công. Trường hợp này, server dùng bộ đếm thời gian. Sau một khoảng thời gian xác định trước mà không nhận được ACK thì client sẽ gửi lại yêu cầu đó.

 Client gửi lại yêu cầu nếu nhận được thông báo hỏng từ server.

 Mất bản tin phản hồi từ server gửi trả về client: ta cần thiết kế các yêu cầu có đặc tính không thay đổi giá trị (idempotent). Client đánh số thứ tự cho các yêu cầu, server sẽ nhận ra được đâu là yêu cầu đã được gửi lại nhờ các số tứ tự này. Do đó server sẽ không thực hiện lặp lại các yêu cầu. Tuy nhiên server vẫn phải gửi trả về bản tin thông báo yêu cầu nào bị thất lạc. Hoặc ta có thể sử dụng một bit ở phần header của yêu cầu để phân biệt yêu cầu nào là yêu cầu đã được gửi lại.

 Client bị lỗi ngay sau khi gửi yêu cầu tới server: Client gửi yêu cầu tới server rồi bị lỗi trước khi nhận được trả lới từ server gửi về. Công việc mà server thực hiện nhưng không có đích nào đợi để nhận được gọi là một “orphan”. Như thế sẽ gây lãng phí chu kì CPU. Ta có 4 giải pháp được đưa ra trong trường hợp này là:

 Trước khi gửi đi yêu cầu, client stub sẽ tạo ra một bản ghi xác định công việc cần thực hiện này và lưu lại. Như thế, khi được phục hồi sau khi lỗi, client sẽ lấy lại bản ghi đó và và việc thực hiện các orphan đang diễn ra sẽ

Một phần của tài liệu Đề cương Hệ Phân Tán (Có đáp án) (Trang 27 - 46)

Tải bản đầy đủ (DOC)

(58 trang)
w