Sistemas Computacionais Tolerantes a Falhas
Neste artigo são apresentados os conceitos básicos de tolerância a falhas e algumas técnicas que são adotadas para alcançá-la.
Introdução
A importância dos sistemas computacionais é percebida por sua tremenda penetração em diversas áreas de aplicação críticas, como: sistemas de defesa, telecomunicações, sistemas bancários, controle de usinas de energia, dentre outros. Muitos desses sistemas precisam manter o correto funcionamento de suas computações por um longo período de tempo. Alguns não podem contar com facilidade de manutenção no local, como os sistemas espaciais.
Os projetistas de sistemas devem empregar técnicas e metodologias próprias para garantir o correto funcionamento dos sistemas por um longo período de tempo.
Neste artigo, iremos apresentar os conceitos básicos de tolerância a falhas e técnicas para alcançá-la.
Tolerância a falhas em sistemas de computação é alvo de estudo desde a década de 50. O primeiro pesquisador a apresentar trabalhos na área foi Jonh von Neuman que desenvolveu trabalhos de como aumentar a confiabilidade aplicando redundância de circuitos. Outros pesquisadores também contribuíram bastante para a fundamentação da área, é válido citar os nomes de Avizienis que projetou o computador STAR (Self-Testing And Repairing ) um dos primeiros projetos a ter como foco um longo período de missão sem intervenções humanas.
Durante o apogeu do projeto espacial americano, diversas técnicas foram criadas e o campo de estudo em si formatado. Com a expansão da computação e a redução dos custos dos componentes de hardware outros tipos de aplicações também começaram a fazer uso desta área.
Falhas e Sistemas tolerantes a falhas
Para compreendermos como projetar sistemas tolerantes a falhas, primeiro devemos entender como as falhas ocorrem nos sistemas. Existem três palavras básicas que determinam o nível de percepção de um problema no sistema: falha, erro e defeito 1.
Falha é um defeito físico, imperfeição que atinge um componente de hardware ou software. Podemos tomar como exemplo uma solda fria que gera um mau contato entre dois componentes, ou um algoritmo que gera um laço infinito.
O Erro é a conseqüência da falha, o desvio do funcionamento correto.
Por exemplo, se uma das entradas de uma porta AND apresentar um curto
para a referência.

Figura 1
O valor da saída sempre será 0, para qualquer valor da entrada E1. Quando a lógica do sistema tentar ativar a saída da porta, a mesma não irá responder gerando assim o estado errôneo fruto da falha do curto-circuito na entrada E2.
O defeito é a representação do erro para o usuário. No mesmo exemplo anterior, se a porta lógica fosse utilizada para ativar o funcionamento de um motor, o defeito seria o seu não acionamento.
Podemos ver uma relação de hierarquia entre os três termos. A falha causa o erro, que por sua vez gera o defeito que é percebido pelo usuário. Vale ressaltar que estas abstrações podem ser aplicadas a qualquer nível de representação no sistema. Por exemplo, a porta lógica poderia ser a entrada do subsistema A2, e neste caso um possível erro em A2 teria como causa a falha na porta lógica. E assim poderíamos seguir pelas dependências entre os subsistemas aplicando o conceito recursivamente.

As falhas podem ter origem em quatro áreas: especificação, implementação, componentes e fatores externos.
A primeira causa está associada a erros de especificação de projeto, geralmente são erros de: levantamento dos requisitos, algoritmos e arquitetura. A próxima causa de falhas é implementação, que se origina de uma leitura incorreta da especificação do projeto. Essas falhas são adicionadas devido a projetos mal realizados, componentes mal selecionados e erros de codificação.
A próxima causa é defeito de componentes, que está
relacionada a imperfeições do processo de manufatura e envelhecimento
dos componentes. Os distúrbios externos são a última causa, exemplos:
radiações eletromagnéticas, erros do operador e condições ambientais
extremas.
Fases da Tolerância a Falhas
Tolerância a falhas é definida como sendo a propriedade de um sistema operar corretamente mesmo na presença de falhas (cf. JOHNSON, 1989, pg. 39). Iremos descrever as quatro etapas que fornecem os meios para obtenção da tolerância a falhas.
Detecção de Erros
O ponto de início de qualquer estratégia de tolerância a falhas é a detecção de um estado errôneo, que é aquele que na ausência de qualquer ação corretiva, pode levar o sistema a um defeito (cf. ANDERSON e LEE, 1981, pg. 113). Dito isso é razoável pensar que o sistema de detecção de erros deve ser o melhor possível, garantindo que nenhum erro deixe de ser detectado. Para tal, seria preciso que o nosso testador obedecesse três regras:
-
Ser baseado somente na especificação do projeto;
-
Testar completamente todo o comportamento do sistema;
-
Ser independente do sistema.
Estas condições são extremamente rigorosas e inviáveis em sistemas reais. As técnicas que são comumente usadas se baseiam em critérios de aceitabilidade, que está abaixo de absoluta retidão e não garante a ausência total de erros. Testes de aceitabilidade levam em consideração o comportamento do sistema e do ambiente, o sucesso dos testes depende da capacidade do projetista de identificar situações de possível falha.
Existem vários meios de realizar a checagem de erros em sistemas computacionais, mas podemos salientar as seguintes:
-
Testes de Replicação – Requer que partes ou todo o sistema seja replicado de modo que seja possível comparar as saídas das réplicas e por votação identificar o resultado correto da computação. Um sistema bastante utilizado baseado nessa técnica é o TMR (Triple Modular Redundant) que é composto por três módulos idênticos na funcionalidade e um votador. Podem-se construir sistemas com mais de três módulos para melhorar a confiabilidade total, tais sistemas são chamados NMR (N Modular Redundant).
-
Testes de Tempo – Se a especificação do sistema requer uma limitação de tempo para realização de uma computação, pode ser adicionado um teste para verificar se esse requisito está sendo atendido. Um exemplo clássico é o contador de timeout utilizado em protocolos de comunicação. Caso não seja recebida uma confirmação de recebimento da mensagem dentro de tempo limite, uma exceção é gerada para notificar o processo que enviou a mensagem.
-
Testes Reversos – Muitas operações possuem relação de um para um entre entrada e saídas, é possível criar uma operação que faça essa relação ao inverso de modo que: toda vez que for realizada a operação, seu inverso seja calculado para testar se houveram erros durante a computação.
-
Testes de Representação de Dados – Muitas estruturas de dados contam com um campo específico que indica se a estrutura está coerente, campos de checagem são bastante comuns em protocolos de comunicação e sistemas de arquivos. Podemos citar: o bit de paridade, checksum e o CRC.
-
Testes por Absurdo2 – Algumas computações têm seu valor de saída limitado a certo intervalo, exemplo não existe seno de um ângulo maior do que 1. O teste por absurdo valida se os resultados das operações estão dentro dos limites especificados.
Confinamento dos Danos
Existe uma latência entre a criação do estado errôneo e sua detecção, esse período permite que as conseqüências do erro (danos) sejam espalhadas para outras partes do sistema. Por isso é importante que exista uma fase que mensure a abrangência do erro e limite sua área de atuação.
Determinar os componentes do sistema que foram contaminados pelo erro detectado, não é uma tarefa simples. Podem-se utilizar técnicas que monitoram o fluxo de informação entre os componentes e dessa maneira dinamicamente determinar a extensão dos danos.
Recuperação de Erros
Após a detecção de erros e seu confinamento é hora de colocar o sistema de volta ao seu estado correto, essa ação é realizada na fase de recuperação de erros. Antes de detalhar as técnicas de recuperação de erros é necessário classificar as falhas em duas categorias:
-
Falhas Antecipadas – O projetista previu, pela natureza do sistema, que alguns tipos de exceções eram factíveis de ocorrer e que para elas existe uma rotina de tratamento de erro conhecida. Ex.: Uma divisão por um número nulo.
-
Falhas não Antecipadas – São falhas que não possuem uma previsão precisa dos danos que podem causar ou como podem ser tratadas.
A única forma de recuperar um sistema de uma falha não antecipada é adotar uma abordagem compreensiva para remoção dos erros, colocando-o em um estado conhecido que irá assegurar continuidade no funcionamento.
A recuperação de erros pode ser para trás ou para frente, ou seja, colocar o sistema em um estado anterior ou em um novo estado, que se espera seja livre de erros. Geralmente, recuperação para frente só funciona com falhas antecipadas.
A recuperação para trás é baseada em pontos de retorno (checkpoints), que são backups da configuração do sistema em determinados momentos do passado. Dessa forma é possível, através de um ponto de retorno, realizar um roll back e voltar a executar em um dado momento do sistema. Alguns sistemas operacionais modernos contam com mecanismos parecidos de recuperação de erros.
Tratamento da Falha e Serviço Continuado
As três fases anteriores preocupam-se em tratar apenas os erros, deixam as falhas que originaram os erros sem tratamento. É possível que a falha volte a gerar repetidamente o mesmo erro, que podem levar a um defeito mesmo com o emprego das técnicas de tolerância a falhas.
Antes de tratar a falha, deve-se localizar o seu ponto de manifestação. Pode-se empregar o uso de testes de auto-diagnóstico, para identificar qual componente está falho.
Após a identificação do local da falha é necessário realizar o reparo do sistema. O reparo pode ser de três formas:
-
Manual – executado por um agente externo ao sistema;
-
Dinâmico – quando motivado por instruções do ambiente, o sistema faz o reparo;
-
Espontâneo – quando todas as ações são iniciadas e executadas pelo sistema.
O método mais simples de reparo é a substituição do componente defeituoso, alguns sistemas fazem uso de módulos extras que podem ser acionados quando o módulo em uso falha. Essa troca pode ser fria, quando o módulo extra estava desligado anteriormente, ou quente, com o módulo extra funcionando e assumindo as funções do outro com pequena interrupção.
Outros sistemas quando detectam a falha optam por realizar o fornecimento degradado dos serviços, ou seja, para de atender algumas solicitações menos prioritários, mas continuam executando as rotinas principais.
Conclusão
Tolerância a falhas deixa de ser utilizada apenas em sistemas especiais, e vira um requisito importante em todos os projetos de sistemas computacionais. É imperativo que os conceitos básicos da área estejam bem disseminados entre os profissionais responsáveis por especificar, projetar e desenvolver novos equipamentos eletrônicos, produtos de consumo e softwares.
Este artigo introduziu os conceitos fundamentais de tolerância a falhas em sistemas computacionais, para um estudo mais detalhado sugerimos uma análise das referências utilizadas.
Referências
JOHNSON, W. Barry.Design and Analysis of Fault Tolerant Digital Systems.1. Addison Wesley, ed. 1989.
ANDERSON, T., LEE, P. A. Fault Tolerance Principles and Pratice. Prentice Hall International, 1. ed. 1981.
WEBER, Taisy Silva. Tolerância a falhas: Conceitos e Exemplos. UFRGS. Disponível em: http://www.inf.ufrgs.br/~taisy/disciplinas/textos/ConceitosDependabilidade.PDF
1 Do Inglês fault, error and failure
2 O termo em inglês é: Reasonableness Check. Nossa tradução é baseada na proximidade de seu significado com a expressão prova por absurdo, usada em lógica matemática.
Otávio Alcântara
otavio@eletronica.org
Otávio Alcântara é Tecnólogo em Telemática pelo CEFET-CE e especializado em desenvolvimento de software em tempo real para sistemas embarcados.
