Giter Site home page Giter Site logo

ces27-lab2's Introduction

CES-27 - LAB 2 - Dynamo

Instruções para configuração do ambiente: Setup
Para saber mais sobre a utilização do Git, acessar: Git Passo-a-Passo
Para saber mais sobre a entrega do trabalho, acessar: Entrega

Referências

O paper no qual essa atividade é baseada pode ser encontrado em: Dynamo: Amazon’s Highly Available Key-value Store

Executando o Código

Durante a execução dessa atividade, será necessário que sejam inicializadas quatro instâncias do serviço proposto. O arquivo main da execução(server.go) se encontra na pasta raiz do projeto.

A primeira instância pode ser inicializada como mostrado a seguir:

$ go run server.go

[SERVER] Running Dynamo Server with id 'localhost:3000'
[RING] Added node 'localhost:3000'(hostname: 'localhost:3000') to the local ring(hash: '795')
[SERVER] Listening on 'localhost:3000'

As demais instâncias devem utilizar o seguinte comando (incrementando o parâmetro port para cade instância a mais):

$ go run server.go -port 3001 -ring localhost:3000

[SERVER] Running Dynamo Server with id 'localhost:3001'
[RING] Added node 'localhost:3000'(hostname: 'localhost:3000') to the local ring(hash: '795')
[RING] Added node 'localhost:3001'(hostname: 'localhost:3001') to the local ring(hash: '165')
[RING] Reporting to host 'localhost:3000'
[SERVER] Listening on 'localhost:3001'

Para evitar erros de sincronização, aguarde um pouco entre a inicialização de cada uma das instâncias.

O Resultado da execução é mostrado a seguir: Run All

Console

Para simplificar a interação com o servidor, é possível entrar com comandos durante a execuçao do serviço como mostrado a seguir:

ring

[CONSOLE] HASH__|ID_______________|
[CONSOLE] '165'|'localhost:3001'|
[CONSOLE] '473'|'localhost:3003'|
[CONSOLE] '543'|'localhost:3002'|
[CONSOLE] '795'|'localhost:3000'|

Lista de comandos disponíveis: put key value - put KV(key ,value) pair on this instance only
rput key value quorum - route a put request (the same as if an external client made a put request) using a write quorum
get key - get a the value associated with the given key
rget key quorum - route a get request (the same as if an external client made a get request) using a read quorum
print - print all the data stored in this instance
ring - print the topology of the ring structure
down - set the server as down (unavailable)
up - set the server as up (available)

Hash Consistente

Na primeira parte da atividade, vamos corrigir o funcionamento do hash consistente.

Abra o arquivo common/consistenthash/consistenthash.go:

A função a seguir não possui o código necessário para a correta distribuição dos dados entre os nós.

// search will find the index of the node that is responsible for the range that
// includes the hashed value of key.
func (r *Ring) search(key string) int {
    /////////////////////////
    // YOUR CODE GOES HERE //
    /////////////////////////

    return 0
}

Ao sempre retornar zero, a função redireciona todas as operações de leitura e escrita para o mesmo nó.

Para verificar o problema, basta executar o seguinte comando:

rput alice hi 2

[ROUTER] Routing Put of KV('alice', 'hi') with quorum Q('2').
[ROUTER] Trying 'localhost:3001' as coordinator.

A primeira tentativa de roteamento da key "alice" deveria ser o nó com id "localhost:3000", mas por conta do erro na função search, sempre é escolhido o nó com id "localhost:3001" pois este é o primeiro da lista(índice 0).

ring

[CONSOLE] HASH__|ID_______________|
[CONSOLE] '165'|'localhost:3001'|
[CONSOLE] '473'|'localhost:3003'|
[CONSOLE] '543'|'localhost:3002'|
[CONSOLE] '795'|'localhost:3000'|

Ao implementar a função search corretamente, o comando acima deve resultar em:

rput alice hi 2

[ROUTER] Routing Put of KV('alice', 'hi') with quorum Q('2').
[ROUTER] Trying 'localhost:3000' as coordinator.

Pois o código abaixo:

func hashId(key string) uint32 {
    return crc32.ChecksumIEEE([]byte(key)) % uint32(1000)
}

retorna o hash 735

Versionamento usando Timestamps

Na segunda parte desta atividade, vamos implementar a utilização de comparação de timestamps para decidir entre diferentes versões de uma mesma chave, o que pode acontecer quando um ou mais servidores ficam indisponíveis.

Para verificar o problema, execute os seguintes comandos:

Adiciona uma chave cujo hash caia dentro do range do servidor 3000:

rput alice hi 2

[ROUTER] Routing Put of KV('alice', 'hi') with quorum Q('2').
[ROUTER] Trying 'localhost:3000' as coordinator.

O sistema de replicação vai então colocar cópias dos dados no servidores 3001 e 3003.

2016/10/06 09:00:29 [INTERNAL] Replicating 'alice' = 'hi' (timestamp: '1475755228')

Agora deixe o servidor 3000 indisponível:

down

[CONSOLE] Putting server DOWN.
[SERVER] Server Stopped

Escreva um novo valor para a chave utilizada acima:

rput alice oi 2

[ROUTER] Routing Put of KV('alice', 'oi') with quorum Q('2').
[ROUTER] Trying 'localhost:3000' as coordinator.
[ROUTER] Coordinator tryout failed. Error: dial tcp [::1]:3000: connectex: No connection (...)
[ROUTER] Trying 'localhost:3001' as coordinator.
[ROUTER] Coordinate succeded.

Como o servidor 3000 está indísponível, o próximo coordenador é o seguinte a ele no anel, nesse caso o servidor 3001.

O valor foi atualizado em 3001 e 3003, mas não em 3000 pois este está indisponível:

[COORDINATOR] Error on replication: dial tcp [::1]:3000: connectex: No connection could be made because the target machine actively refused it.

Reative o servidor 3000:

up

[CONSOLE] Putting server UP.
[SERVER] Listening on 'localhost:3000'

Observe que o servidor 3000 possui a versão antiga da chave:

print

[CONSOLE] KEY_____|VALUE_|TIMESTAMP_|
[CONSOLE] 'alice'|'hi'|0______|

Realize uma requisição Get pela chave:

rget alice 2

[COORDINATOR] Coordinating voting of K('alice') with Quorum '2'
[CACHE] Getting Key 'alice' with Value 'hi' @ timestamp '0'
[COORDINATOR] Voting with quorum '2' succeded.
[COORDINATOR] Vote: hi
[COORDINATOR] Vote: oi

E o resultado:

[ROUTER] Coordinate succeded.
[CONSOLE] Rget result: 'alice' = 'hi'

Esse erro (receber "hi" ao invés do último valor "oi") pois o serviço não utiliza a compara ção de timestamps. Ao invés disso, ele sempre seleciona o primeiro elemento da lista de votos.

Para corrigir o problema, é necessário alterar duas coisas:

O arquivo dynamo/cache.go não armazena as timestamps recebidas durante a gravação:

// Put a value to a key in the storage. This will handle concurrent put
// requests by locking the structure.
func (cache *Cache) Put(key string, value string, timestamp int64) {
    log.Printf("[CACHE] Putting Key '%v' with Value '%v' @ timestamp '%v'\n", key, value, timestamp)

    cache.Lock()
    cache.data[key] = value
    cache.Unlock()

    return
}

Você precisa alterar esse arquivo (não somente esse método) para armazenar e retornar corretamente a timestamp associada a um dado.

Quando a implementação estiver correta, o valor de timestamp retornado pelo cache deve ser o mesmo que o foi passado durante a gravação.

[CACHE] Putting Key 'alice' with Value 'hi' @ timestamp '1475755228'
[CACHE] Getting Key 'alice' with Value 'hi' @ timestamp '1475755228'

Por último, no arquivo dynamo/coordinator.go você deve implementar a função abaixo:

// aggregateVotes will select the right value from the votes received.
func aggregateVotes(votes []*vote) (result string) {
    for _, vote := range votes {
        log.Printf("[COORDINATOR] Vote: %v\n", vote.value)
    }

    /////////////////////////
    // YOUR CODE GOES HERE //
    /////////////////////////

    result = votes[0].value
    return
}

ces27-lab2's People

Contributors

pauloaguiar avatar

Stargazers

 avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

ces27-lab2's Issues

Erro ao tentar fazer o get do projeto pelo Git

Boa tarde, Paulo.
Ao tentar fazer o get do projeto pelo Git, tive um erro:

iMac-de-Carlos:~ carlosballock$ go get -d github.com/pauloaguiar/ces27-lab2
# cd .; git clone https://github.com/pauloaguiar/dynamo-lab2 /Developer/Go/Workspace/src/github.com/pauloaguiar/dynamo-lab2
Cloning into '/Developer/Go/Workspace/src/github.com/pauloaguiar/dynamo-lab2'...
remote: Repository not found.
fatal: repository 'https://github.com/pauloaguiar/dynamo-lab2/' not found
package github.com/pauloaguiar/dynamo-lab2/dynamo: exit status 128
iMac-de-Carlos:~ carlosballock$ go get -d github.com/pauloaguiar/ces27-lab2

Por favor, você poderia verificar?
Abraços,

Ballock.

Comando "down" no servidor não está impedindo que o cache seja atualizado

Paulo,
Segui o procedimento da seção "Versionamento usando Timestamps" e "derrubei" o servidor com o comando down. Porém, quando eu dei o comando rput alice oi 2, verifiquei que o servidor também teve seu cache local atualizado antes mesmo dele ser "reativado" com o comando up (verifiquei isso com o comando get alice no servidor).
Por favor, você poderia verificar esse problema?
Abraços,

Ballock.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.