Você está na página 1de 8

Implementação de uma Ferramenta Didática para Simulação

de um Sistema de Transações Distribuídas


Adriano Fiad Farias, Marcos Roberto Ribeiro

Faculdade de Computação - Universidade Federal de Uberlândia (UFU);


Uberlândia – MG – Brasil.
{adrifiad,mribeiro}@pos.facom.ufu.br

Abstract. An implementation of the concurrency control must among other


things, to guarantee the consistence of the base of data, avoiding like this the
existent conflicts among the concurrency transactions. This article presents an
implementation from a multiplatform didactic tool, for a simulation from a
distributed system of the running, that uses the Strict Timestamp Ordering
(STO) and Two-phase Commit (2PC) protocols. Using this tool, can observe
with details the running of this protocols, as well as, testing in possible failure
situations from a distributed system.

Resumo. Uma implementação de controle de concorrência deve entre outras


coisas, garantir a consistência da base de dados, evitando assim os conflitos
existentes entre as transações concorrentes. Este artigo apresenta uma
implementação de uma ferramenta didática multiplataforma, para simulação
do funcionamento de um sistema distribuído, que utiliza os protocolos Strict
Timestamp Ordering (STO) e Two-phase Commit (2PC). Com o uso desta
ferramenta, pode-se verificar com detalhes o funcionamento destes
protocolos, bem como, testá-los em possíveis situações de falhas em um
sistema distribuído.

1. Introdução
Existem situações cotidianas que tornam necessário a distribuição de dados em
diferentes locais, separados geograficamente. Uma instituição bancária é um exemplo,
pois possui várias agências e em cada uma delas possui clientes relacionados à mesma.
É, no entanto, importante que um cliente de uma determinada agência possa efetuar
operações sem ter que estar localizado em sua agência. É em aplicações do cotidiano
como esta que pode-se verificar a necessidade da utilização de sistemas distribuídos.
Os sistemas distribuídos são difíceis de serem modelados e de se implementar,
por causa da imprevisibilidade e demora na transferência de mensagens, velocidade de
execução de processos e tratamento de falhas. Tais variáveis tornam o sistema
vulnerável a anormalidades, principalmente quando este estiver executando uma
transação envolvendo diversas operações [Raynal and Singhal 2001].
Neste trabalho será implementada uma ferramenta didática para simular o
funcionamento de um sistema distribuído utilizando os protocolos Strict Timestamp
Ordering (STO) e Two-Phase Commit (2PC). A implementação foi desenvolvida na
linguagem Java e o sistema dividido em três módulos, um gerenciador de transações
distribuídas (GTD), um gerenciador de transações locais (GTL) e um programa usuário
(PU).
Este artigo está organizado em sete seções. Na seção 2 é apresentada uma breve
noção sobre conceitos de controle de concorrência. Em seguida, na seção 3, são
descritos os protocolos utilizados. A seção 4 apresenta como foi implementado o
modelo de sistema distribuído proposto. Formas de recuperação de falhas são mostradas
na seção 5. Os resultados obtidos através da ferramenta são apresentados na seção 6, e
por fim, a seção 7, exibe as conclusões obtidas na realização deste trabalho.

2. Controle de concorrência
Em um sistema que interage com múltiplos usuários é fundamental o controle do
conjunto de operações realizadas por cada usuário. Tal conjunto de operações recebe o
nome de transação.
Quando há mais de uma transação acessando um mesmo item de dado deve
existir um controle de concorrência sobre as mesmas. O principal objetivo do controle
de concorrência é garantir que as transações sejam executadas corretamente. Isto é, uma
transação não deve interferir na execução de outra transação e quando uma transação
termina, normalmente todas as suas ações devem se tornar permanentes. Em um
ambiente distribuído o controle de concorrência torna-se bem complexo, pois as
transações podem executar operações em diversos sites [Bernstein et al. 1987].

3. Protocolos Utilizados
Neste artigo, propõe-se, a utilização de dois protocolos, o protocolo Strict Timestamp
Ordering (STO) para controlar a concorrência entre transações e o protocolo Two-phase
Commit (2PC) para garantir a consolidação das transações.

3.1. Strict Timestamp Ordering (STO)


O protocolo Timestamp Ordering (TO) utiliza um identificador único para cada
transação, chamado timestamp. O timestamp é atribuído no início da transação e todas
as operações devem conter o timestamp da sua respectiva transação. O protocolo TO
controla a concorrência das transações, impondo uma ordem de execução para as
operações conflitantes. As operações conflitantes são aquelas que operam sobre o
mesmo item de dado. Este método segue a seguinte regra, chamada de regra TO.
Regra TO: Seja pi(x) uma operação da transação i sobre o item de dado x e ts(Ti)
o timestamp de uma transação i. Se pi(x) e qj(x) são operações conflitantes, então a
operação pi(x) deve preceder qj(x) se e somente se, ts(Ti) < ts(Tj) [Bernstein et al. 1987].
O protocolo TO não garante a recuperabilidade das transações, ou seja, se uma
transação T2 lê um item de dado gravado por T1, então à transação T1 deve consolidar
antes de T2. Para garantir a recuperabilidade é utilizada uma variação do protocolo TO o
Strict Timestamp Ordering (STO). O protocolo STO também faz uso da regra TO,
porém após receber uma operação de escrita de T1 e uma operação de leitura de T2 sobre
o mesmo item de dado, o protocolo STO atrasa a consolidação de T 2 até que T1 esteja
consolidada [Özsu and Valduriez 2001].

3.2. Two-Phase Commit (2PC)


O protocolo 2PC é um dos mais simples e populares protocolos de consolidação
atômica. O seu nome se deve às duas fases que compõem o protocolo, uma fase de
verificação e outra de efetivação. Em um ambiente distribuído pode-se considerar que,
para uma transação, há vários sites participantes e um site coordenador. O site
coordenador será responsável por controlar o processo de consolidação [Bernstein et al.
1987]. As duas fases do protocolo 2PC são descritas a seguir.
Fase 1 (Verificação):
1. O coordenador envia uma requisição de consolidação para todos os
participantes.
2. O participante, ao receber a requisição de consolidação, reponde com uma
mensagem de “sim” ou “não” para o coordenador. Quando a resposta é “não”
o participante já aborta a transação.
Fase 2 (Efetivação):
1. Quando o coordenador recebe as respostas de todos os participantes, toma-se
a decisão sobre a consolidação da transação. Se todas as respostas forem
“sim” o coordenador envia uma confirmação de consolidação para todos os
participantes. Caso contrário será enviada uma requisição de cancelamento a
todos os participantes que votaram “sim”.
2. Cada participante que votou “sim” aguarda uma requisição de cancelamento
ou confirmação, para abortar ou consolidar a transação respectivamente.
O funcionamento do protocolo 2PC pode ser visto na Figura 1.

Figura 1. Funcionamento do protocolo 2PC [Bernstein et al. 1987].


4. Implementação
O modelo de sistema distribuído descrito foi implementado com o uso da linguagem
Java, tornando assim sua execução multiplataforma [Gosling et al. 2000], A ferramenta
desenvolvida foi divida em três módulos GTD, GTL e PU. O módulo GTD implementa
as funcionalidades do coordenador, o módulo GTL implementa as funcionalidades dos
participantes e o módulo PU implementa um console para comunicação com o usuário.
A interação entre os módulos do sistema implementado é exibida na Figura 2.

Figura 2. Interação entre os módulos do sistema desenvolvido.

Para comunicação entre os módulos utilizou-se de soquetes garantindo assim um


melhor desempenho [Torres 2001], onde as mensagens apresentam um formato
padronizado. Como pode haver mais de um PU conectado ao GTD, faz-se necessário o
uso de Threads para a comunicação simultânea com estes PU's [Lea 1999]. Além disso,
foram implementados alguns métodos de sincronismo, ou seja, não permitido que se
tenham métodos executando simultaneamente.
As funcionalidades didáticas da implementação são observadas durante a
execução, através de mensagens em modo texto, que serão apresentadas na seção 6. Os
módulos GTD e PU exibem mensagens a cada operação que é emitida pelo usuário,
assim pode-se observar como as transações são escalonadas e o desenvolver do processo
de consolidação.

4.1. Módulo GTD


O módulo GTD é responsável pela gerência do sistema distribuído, realizando o
controle de concorrência das transações e a comunicação com os demais módulos.
Para executar o GTD deve ser fornecido o número de sites participantes, ou seja,
o número de GTL’s (1 a n) e o número de ítens de dados que cada GTL possuirá (1 a n),
se não for fornecido nenhum item de dado, o GTL é iniciado por padrão com 100 ítens.
Ao iniciar, o GTD aguarda a conexão de cada GTL e, para cada GTL que se
conecta, é enviada uma mensagem com o número de ítens de dados. Após a conexão de
todos os GTL’s, o GTD aguarda a conexão de algum cliente PU.
A comunicação com mais de um PU é controlada através de uma fila de
operações pendentes. A cada operação de manipulação de ítens de dados que entra na
fila, é verificada a sua possibilidade de ser processada, de acordo com o protocolo STO.
Assim a operação pode ser processada imediatamente, caso não haja nenhuma restrição.
Caso o processamento não seja imediato, é verificado se o timestamp da
operação é maior do que o timestamp do item de dado a ser manipulado e a operação
entra em espera (wait). Porém se o timestamp da operação for menor do que o item de
dado a ser manipulado, toda a transação é re-submetida para que a operação possa ser
realizada.
Quanto às operações de encerramento de transação, commit ou abort, o controle
segue as especificações do protocolo 2PC. A operação abort pode ser enviada pelo PU
ou gerada automaticamente quando houver alguma falha na comunicação.
Por meio das mensagens exibidas pelo GTD, é possível observar a inicialização
de cada GTL e se um GTL se tornar indisponível. Além disso, pode-se constatar o
processamento de cada operação, verificando se uma transação inicia, entra em wait ou
é resubmetida.

4.2. Módulo GTL


O GTL inicia a comunicação com o GTD e recebe uma mensagem com o número de
ítens de dados que deve possuir. Para fins empíricos, é criado um arquivo preenchido
com ítens de dados aleatórios. Após inicialização o GTL aguarda alguma operação do
GTD.
Quando o GTL recebe uma mensagem de leitura para um item de dado, busca o
primeiro na cache, caso não seja encontrado busca em sua base e retorna uma mensagem
para o GTD com o valor do item de dado pedido.
Ao receber uma mensagem de gravação para um item de dado, o GTL faz uma
leitura prévia deste item e retorna para o GTD o valor anterior do mesmo. A alteração é
realizada somente na cache e é armazenado o identificador da transação que realizou a
gravação.
Uma mensagem de abort recebida pelo GTL, faz com que todos os ítens de dado
em cache que foram gravados pela transação que abortou sejam apagados. Enquanto
uma mensagem de commit leva o GTL a atualizar o arquivo consolidando-o, com os
ítens de dado em cache que foram gravados pela transação.

4.3. Módulo PU
Ao ser iniciado o módulo PU busca se conectar com o GTD e, recebe o timestamp da
transação. A classe PU simplesmente captura os comandos digitados pelo usuário e
envia para o GTD. Os possíveis comandos são: read(x), write(x, valor), commit e abort.
Os comandos read e write enviam mensagens de leitura e gravação respectivamente. O
comando abort envia uma mensagem para abortar uma transação e o comando commit
uma mensagem para consolidar uma transação.
O módulo PU exibe a resposta de cada operação enviada. Quando uma transação
entra em espera, a execução do PU é bloqueada até que a operação bloqueante seja
processada.
5. Detecção e recuperação de falhas
O protocolo 2PC não está livre de falhas, há momentos em que o GTD ou o GTL devem
aguardar uma mensagem para prosseguir com seu processamento. Desta maneira, pode
acontecer uma espera indefinida, este problema pode ser resolvido através de timeouts.
Assim, após um determinado tempo de espera, uma ação especial poderá ser realizada, a
esta ação dá-se o nome de ação de timeout [David and Son 1993].
Uma ação de timeout consegue identificar uma falha e interromper a execução
do sistema, entretanto ainda é necessário que o sistema possa se recuperar de uma falha.
O uso de arquivos de log é o principal método utilizado na recuperação de falhas de um
sistema distribuído. O sistema distribuído implementado não apresenta uma recuperação
de falhas completa, mas grava em arquivos de log as informações necessárias para uma
possível recuperação [Bernstein 1987]. Cada linha dos arquivos de log gravados
apresenta um identificador da transação e a operação que for realizada.
O GTD grava em log o início de uma transação, todas as operações de escrita e o
encerramento de uma transação. No encerramento de uma transação o GTD grava uma
mensagem de início de encerramento antes de enviar as requisições de consolidação
para os GTL's. Se o encerramento da transação for para abortar, o GTD apenas grava em
log que a transação foi encerrada. Se o encerramento for para consolidar, o GTD grava
em log a resposta de cada GTL e, após decidir sobre a consolidação, grava o
encerramento da transação.
Quando o GTL recebe uma requisição de consolidação do GTD, grava-se em log
a resposta à requisição. Ao receber a confirmação de consolidação do GTD, grava-se o
encerramento da transação em log.
As ações de timeout e os arquivos de log são indispensáveis para a recuperação
de falhas do sistema. As ações de timeout detectam possíveis falhas e os arquivos de log
possuem a situação das transações correntes no momento que ocorreu a falha.
Se ocorrer uma falha o sistema utilizará as informações dos arquivos de log,
todos os sites serão sincronizados e o sistema retornará ao estado anterior à falha. Por se
tratar de um sistema distribuído, caso haja falhas em GTL's que não estiverem
envolvidas com nenhuma transação, não comprometerão o funcionamento do sistema
[Raynal and Singhal 2001].

6. Resultados
Para realizar os testes considerou-se as operações r(x) como sendo leitura do item de
dado x, w(x,y) operação que grava o valor y no item de dado x, c como commit,
consolidação de uma transação e a como abort, aborta uma transação.
O resultado do processamento de uma transação pode ser visto no respectivo
módulo PU que a iniciou, além disso, no módulo PU pode visualizar todas as operações,
de todas as transações, percebendo seu escalonamento e consolidação.
Foram realizados alguns testes, sendo os mais importantes, teste de resubmissão
de uma transação e teste de falha na consolidação. Para a realização destes testes,
instanciamos o GTD com apenas 2 sites (GTLs) e cada site com 100 itens de dados.

r1(2), w2(1, 100), r1(1), c2, c1

GTD: iniciando
GTD: aguardando conexão com GTL's
GTD: GTL 0 iniciado
GTD: GTL 1 iniciado
GTD: executando
GTD: t1 iniciada
GTD: t1: leitura para GTL 0
GTD: t1: r(2) = 43221
GTD: t2 iniciada
GTD: t2: gravação para GTL 0
GTD: t2: w(1, 100)
GTD: t1: leitura para GTL 0
GTD: t1: r(1) = 43221
GTD: t1: resubmetida t3
GTD: t3: leitura para GTL 0
GTD: t3: r(2) = 43221
GTD: t3: leitura para GTL 0
GTD: t3: WAIT
GTD: t2: c
GTD: t2: begin commit
GTD: t2: GTL 0: c
GTD: t2: finalizada
GTD: t2: consolidada
GTD: t3: leitura para GTL 0
GTD: t3: r(1) = 100
GTD: t3: c
GTD: t3: begin commit
GTD: t3: GTL 0: c
GTD: t3: finalizada
GTD: t3: consolidada
Exemplo de teste de resubmissão.
No teste de resubmissão, existem duas operações conflitantes (t1 e t3), sobre um
mesmo item de dado, mas de transações diferentes. No entanto, a operação com
timestamp menor é recebida por último, esta operação é chamada de operação atrasada.
Para solucionar tal problema, o GTD, aborta a transação que emitiu a operação atrasada
e a resubmete com um novo timestamp. Desta forma, na pior das hipóteses, a transação
com o novo timestamp apenas entrará em wait.
w1(1,100),w1(150,100),c1

GTD: iniciando
GTD: aguardando conexão com GTL's
GTD: GTL 0 iniciado
GTD: GTL 1 iniciado
GTD: executando
GTD: t1 iniciada
GTD: t1: gravação para GTL 0
GTD: t1: w(1, 100)
GTD: t1: gravação para GTL 1
GTD: t1: w(150, 100)
** Neste momento paramos o GTL 1 **
GTD: t1: c
GTD: t1: begin commit
GTD: t1: GTL 0: c
GTD: t1: GTL 0: a
GTD: t1: finalizada
GTD: t1: abortada
Exemplo de teste de falha na consolidação.
Neste teste (falha de consolidação), é demonstrado o funcionamento do
protocolo 2PC, realizou-se gravações nos dois GTL's em execução e antes de emitir a
operação de consolidação, o segundo GTL (GTL 1) foi desativado, quando o GTD
solicita a confirmação de consolidação dos GTL's, não é recebida a resposta do GTL 1 e
a transação é abortada.

7. Conclusão
Após o término deste trabalho, observa-se a importância de um efetivo controle de
concorrência em sistemas distribuídos, para garantir a consistência dos dados. Outra
importante característica de um sistema distribuído é a recuperação de falhas, para
garantir que caso ocorra alguma falha, os dados alterados continuem intactos, mesmo se
não houve uma gravação permanente.
Com o uso da ferramenta didática implementada é possível analisar, passo a
passo, o escalonamento das operações das transações, bem como, o processo de
consolidação de uma transação no GTD e em todos os GTL's envolvidos. Desta forma
pode-se verificar o funcionamento em detalhe dos protocolos STO e 2PC, além da
possibilidade de testar o sistema em situações de falhas.
Como sugestão de trabalhos futuros, torna-se interessante a implementação de
outros protocolos de escalonamento de transações, controle de concorrência, entre
outros, de uma forma didática para que alunos tenha acesso na prática ao funcionamento
dos mesmos.

Referências
Özsu, M. T. and Valduriez, P. (2001) “Princípios de Sistemas de Banco de Dados
Distribuído”. Editora Campus, Tradução da 2ª edição americana.
Bernstein, P. A., Hadzilacos, V., Goodman, N. (1987) “Concurrency Control and
Recovery in Database Systems”, Addison-Wesley.
Gosling, J., Joy, B. and Steele, G. (2000) “The Java Language Specification”, Addison-
Wesley, second edition.
Lea D. (1999) “Concurrent Programming in Java”. Addison-Wesley, second edition.
Torres, G. (2001) “Redes de Computadores – Curso Completo”, Axcel Books.
David, R. and Son, S. H. (1993) “A secure two phase locking protocol”, IEEE,
Department of Computer Science, University of Virginia.
Raynal, M. and Singhal, M. (2001) “Mastering agreement problems in distributed
systems”, IEEE Software, New York.