• Nenhum resultado encontrado

O Algoritmo de Difusão Confiável Proposto

Uma Proposta de Difusão Confiável Hierárquica em Sistemas Distribuídos Assíncronos

4. O Algoritmo de Difusão Confiável Proposto

Seja i um processo que executa o algoritmo de difusão confiável e d = log2na dimensão

do d-VCube com 2dprocessos. O Algoritmo 1 apresenta o pseudo-código da solução de

difusão confiável proposta.

A função clusteri(j) = s calcula o identificador s do cluster do processo

i que contém o processo j, 1 ≤ s ≤ d. Por exemplo, considerando o 3-VCube da Figura 1, cluster0(1) = 1, cluster0(2) = cluster0(3) = 2 e cluster0(4) =

cluster0(5) = cluster0(6) = cluster0(7) = 3. Três tipos de mensagens são utiliza-

dos: hT REE, mi para identificar a mensagem de aplicação m que está sendo propagada na árvore; hDELV, mi para as mensagens enviadas aos processos considerados falhos,

(a) Sem falhas (b) p4é suspeito

Figura 2. Difusão confiável no processo 0 (p0)

evitando que falsas suspeitas impliquem em não recebimento por processos corretos; e hACK, mi para confirmar o recebimento de m pelo destinatário que recebe TREE. Cada mensagem m contém ainda dois parâmetros: (1) o identificador da origem, isto é, o pro- cesso que iniciou a difusão, obtido com a função source(m); e (2) o timestamp, um contador sequencial local que identifica de forma única cada mensagem gerada em um processo, obtido pela função ts(m). Um processo obtém as informações sobre o estado dos demais processos pelo algoritmo VCube.

As variáveis locais mantidas pelos processos são:

• correcti: conjunto dos processos considerados corretos pelo processo i;

• lasti[n]: a última mensagem recebida de cada processo fonte;

• ack_seti: o conjunto de ACKs pendentes no processo i. Para cada mensagem

hT REE, mi (re)-transmitida por i de um processo j para um processo k, um elemento hj, k, mi é adicionado a este conjunto. O símbolo ⊥ representa um elemento nulo. O asterisco é usado como curinga. Por exemplo, um elemento hj, ∗, mi, por exemplo, representa todos os ACKs pendentes para uma mensagem m recebida pelo processo j e retransmitida para qualquer outro processo.

• pendingi: lista de mensagens m recebidas pelo processo i de um processo fonte

source(m)que ainda não podem ser entregues à aplicação por estarem fora de ordem, isto é, ts(m) > ts(lasti(source(m)) + 1.

Um processo i inicia a difusão invocando o método BROADCAST(m). A linha 7

garante que um novo broadcast só é iniciado após o término do anterior, isto é, quando não há acks pendentes para a mensagem lasti[i]. Nas linhas 9 - 10 a nova mensagem m

é entregue localmente (propriedade de entrega confiável) e em seguida enviada a todos os vizinhos no VCube através da função BROADCAST_TREE. Esta função utiliza BRO- ADCAST_CLUSTERpara enviar mensagens TREE para cada primeiro processo sem-falha

em cada cluster s = 1.. log2n, e mensagens DELV para os processos considerados fa-

lhos (suspeitos). Para cada mensagem TREE enviada, um ack é incluído na lista de acks pendentes. A Figura 2 ilustra exemplos para um VCube de 3 dimensões. A Figura 2(a) mostra uma execução sem falhas considerando o processo 0 (p0) como fonte. Após fazer

a entrega local, p0envia uma cópia da mensagem para p1, p2e p4, que são os vizinhos dele

em cada cluster. Embora p5 também pertença ao mesmo cluster de p4, p0 não envia uma

cópia da mensagem para p5, pois não há aresta no VCube conectando os dois processos.

Quando um processo i recebe uma mensagem hT REE, mi de um processo j (linha 39) ele invoca HANDLE_MESSAGE. Nela é verificado se a mensagem é nova com-

parando os timestamps da última mensagem armazenada em lasti[j]e da mensagem rece-

lasti[j]é atualizado e a mensagem é entregue à aplicação. Em seguida, o processo i ve-

rifica se o processo origem da mensagem está falho. Se a origem ainda é considerada correta, m é retransmitida para os vizinhos em cada cluster interno ao cluster de i que também fazem parte do grupo com os destinatários da mensagem. Isso é feito durante a execução da função BROADCAST_CLUSTER com parâmetro h = clusteri(j)− 1. A

Figura 2(a) ilustra a propagação feita por p4 para p5. Se i é uma folha da árvore (clus-

ters s = 1) ou se não existe vizinho correto pertencente aos destinatários, nenhum ack pendente é adicionado ao conjunto ack_seti e CHECKACKS envia uma mensagem ACK

para j. Por outro lado, se um processo i recebe uma mensagem nova hT REE, mi, mas verifica que source(m) foi detectado como falho, o processo de broadcast é reiniciado considerando a árvore com raiz em i.

Quando uma mensagem hACK, mi é recebida, o conjunto ack_seti é atualizado

e, se não existem mais acks pendentes para a mensagem m, CHECKACKS envia um ACK

para o processo k do qual i recebeu a mensagem TREE anteriormente. No entanto, se k = i, a mensagem ACK alcançou o processo fonte ou o processo que retransmitiu a mensagem após a falha do processo fonte. Nesse caso, a mensagem de ACK não precisa mais ser propagada.

A detecção de um processo falho j é tratada após a notificação do evento Algoritmo 1 Difusão confiável no processo i

1:lasti[n]← {⊥, ..., ⊥}

2:ack_seti← ∅

3:correcti← {0, ..., n − 1}

4:pendingi← ∅

5:procedureBROADCAST(message m)

6: if source(m) = i then

7: wait until ack_seti∩ {h⊥, ∗, lasti[i]i} = ∅

8: lasti[i]← m

9: DELIVER(m)

10: BROADCAST_TREE(⊥,m, log2n)

11: procedureBROADCAST_TREE(process j, message m, inte-

ger h)

12: for all s ∈ [1, h] do

13: BROADCAST_CLUSTER(j,m, s)

14: procedureBROADCAST_CLUSTER(process j, message m, integer s)

15: sent← false

16: for all k ∈ ci,sdo

17: if sent = false then

18: if hj, k, mi ∈ ack_setiand k ∈ correctithen

19: sent← true

20: else if k ∈ correctithen

21: SEND(hT REE, mi) to pk

22: ack_seti← ack_seti∪ {hj, k, mi}

23: sent← true

24: else if hj, k, mi /∈ ack_setithen

25: SEND(hDELV, mi) to pk

26: procedureCHECK_ACKS(process j, message m)

27: if j 6= ⊥ and ack_seti∩ {hj, ∗, mi} = ∅ then

28: if j ∈ correctithen

29: SEND(hACK, mi) to pj

30: procedureHANDLE_MESSAGE(message m)

31: pendingi← pendingi∪ {m}

32: while ∃l ∈ pendingi : (source(l) = source(m)∧ ts(l) = ts(lasti[source(m)]) + 1)

33: or (lasti[source(m)] =⊥ ∧ ts(l) = 0) do

34: lasti[source(m)]← l

35: pendingi← pendingi\{l}

36: DELIVER(l)

37: if source(m) /∈ correctithen

38: BROADCAST(m)

39: upon receive hT REE, mi from pj

40: HANDLE_MESSAGE(m)

41: BROADCAST_TREE(m,clusteri(j)− 1)

42: CHECK_ACKS(j,m)

43: upon receive hDELV, mi from pj

44: HANDLE_MESSAGE(m)

45: upon receive hACK, mi from pj

46: for all k = x : hx, j, mi ∈ ack_setido

47: ack_seti← ack_seti\{hk, j, mi}

48: CHECK_ACKS(k,m)

49: upon notifying crash(process j)

50: correcti← correctir {j}

51: for all p = x, m = y : hx, j, yi ∈ ack_seti∩ {h∗, j, ∗i} do

52: BROADCAST_CLUSTER(p,m, clusteri(j))

53: ack_seti← ack_seti\{hp, j, mi}

54: CHECK_ACKS(p,m)

55: if lasti[j]6= ⊥ then

56: BROADCAST(lasti[j])

57: upon notifying up(process j)

CRASH(j). Três ações são realizadas: (1) atualização da lista de processos corretos; (2)

remoção dos acks pendentes que contém o processo j como destino ou aqueles em que a mensagem m foi originada em j; (3) reenvio das mensagens anteriormente transmitidas ao processo j para o novo vizinho correto k no mesmo cluster de j, se existir um. Esta retransmissão desencadeia uma propagação na nova estrutura da árvore. No exemplo da Figura 2(b), após a notificação de falha de p4, p0retransmite a mensagem para o processo

p5, visto que c0,3 = (4, 5, 6, 7), p5 é o próximo processo sem falha no cluster s = 3. A

propagação continua pelos demais processos corretos do cluster, isto é, p6 e p7. Se p4 é

considerado falho antes do início da difusão, uma mensagem DELV é enviada a ele para garantir o recebimento por p4em caso de falsa suspeita.

5. Conclusão

Este trabalho apresentou uma proposta de solução distribuída para a difusão confiável (broadcast) em sistemas distribuídos sujeitos a falhas de crash em ambientes assíncronos. Árvores com raiz em cada processo são construídas e mantidas dinamicamente sobre uma topologia de hipercubo virtual denominada VCube. Em caso de falhas, os processos são reorganizados de forma a manter as propriedades logarítmicas do hipercubo. Falsas suspeitas são contornadas pelo envio de mensagens adicionais aos processos considerados falhos, porém mantendo-se as principais propriedades do hipercubo.

Como trabalhos futuros, o algoritmo será especificado formalmente, incluindo provas de correção, e testes de desempenho serão realizados por simulação comparando-o com outras soluções.

Referências

Bonomi, S., Del Pozzo, A. e Baldoni, R. (2013). Intrusion-tolerant reliable broadcast. Technical report, Sapienza Università di Roma,.

Chandra, T. D., Hadzilacos, V. e Toueg, S. (1996). The weakest failure detector for solving consensus. Journal of the ACM, 43(4):685–722.

Duarte, Jr., E. P., Bona, L. C. E. e Ruoso, V. K. (2014). VCube: A provably scalable dis- tributed diagnosis algorithm. In: 5th Work. on Latest Advances in Scalable Algorithms for Large-Scale Systems, ScalA’14, pp. 17–22, Piscataway, USA. IEEE Press.

Hadzilacos, V. e Toueg, S. (1993). Fault-tolerant broadcasts and related problems. In: Distributed systems, pp. 97–145. ACM Press, New York, NY, USA, 2 ed.

Liebeherr, J. e Beam, T. (1999). HyperCast: A protocol for maintaining multicast group members in a logical hypercube topology. In: Rizzo, L. e Fdida, S., editores, Networ- ked Group Communication, v. 1736 de LNCS, pp. 72–89. Springer Berlin Heidelberg. Rodrigues, L. A., Duarte Jr., E. P. e Arantes, L. (2014). Árvores geradoras mínimas

distribuídas e autonômicas. In: XXXII Simpósio Brasileiro de Redes de Computadores e Sistemas Distribuídos, SBRC’14.

Ruoso, V. K. (2013). Uma estratégia de testes logarítmica para o algoritmo Hi-ADSD. Dissertação de Mestrado, Universidade Federal do Paraná.

Schneider, F. B., Gries, D. e Schlichting, R. D. (1984). Fault-tolerant broadcasts. Sci. Comput. Program., 4(1):1–15.

Wu, J. (1996). Optimal broadcasting in hypercubes with link faults using limited global information. J. Syst. Archit., 42(5):367–380.