Escolar Documentos
Profissional Documentos
Cultura Documentos
cure:
quando um cliente quer fazer uma transação, o snapshot da transaçao terá que ter no
minimo
todos os timestamps vistos até agora por C. Desta forma, o timestamp vai ser
atribuido
por um coordenador escolhido randomicamente que defenirá o timestamp entre 2
valores:
+ o timestamp mais alto que C já viu
+ o seu próprio (o do coordenador) relógio lógico.
Quando a transação prosseguir será-lhe atribuido um commit timestamp segundo um 2PC
em que todos as partições que guardem valores que T alterou vão sugerir valores
para
esse commit. Escolhe-se o valor máximo destes valores. Não pode haver commit's z<Y
para qualquer servidor
Esse timestamp será guardado nos valores associados ao que a transação escreveu.
Como
o timestamp de commit é maior que o timestamp da transação, fica guardado que para
escrever
esses valores é preciso os items que estavam em S.
wren:
usa o LST e o RST que contem o maior timestamp instalado em todas as particoes da
DC
(de forma local e de forma remota).
E usa também uma client cache para guardar o que um cliente especifico já escreveu
mas
ainda não foi escrito para todas as particoes.
Presumo que a parte de commit seja igual ao do cure porque não aborda isso.
BDT:
Usa os Lst e o RST para calcular as dependencias. à partida só usa estes dois
timestamps.
Bist:
esta merda é o protocolo responsavel por calcular o LST e o Rst.
Todas as particoes vao saber o LST e o RST para o seu DC local.
Elas mandam umas para as outras os seus valores maximos de remote e local
(periodicamente e depois pronto
deve ser usado consensu presumo eu.
HlC:
juncao de physical clocks com logical cloks.
Será o máximo entre o physical clock e o (logical_clok + 1), assim o clock dele
avança
mesmo sem receber eventos/transaçoes o que faz com que o cliente possa dar prune na
sua
cache uma vez que os timestamps já vistos dessa particao estao a aumentar.
availability:
está sempre disponivel. Mesmo que uma Dc remota vá abaixo o que pode impedir o RST
de
ser o correto, ele simplesmente atribui esse RST à transação o que faz com que ela
possa
andar para a frente e mesmo assim proceder à transação. Em caso de read vai ler uma
versão
antiga, em caso dee write deposi terá o seu commit time. Simplesmente no caso do
write
ele acha que precisa de os items que estavam em rst.
metadados
item
+ k (key)
+ v (value)
+ ut (timestamp commit)
+ rdt (remote dependecy time)
+ idt (id transacao que o criou)
+ st (source replica do item)
client
+ idc (current transaction)
+ lst (local timestamp)
+ rst (remote timestamp)
+ hwtc (commit time of last update transaction)
+ WSc (write's client set)
+ RSc (read's client set)
+ WCc (client side cache)
servers
+ n (partition id)
+ m (local DC id)
+ Clock mn (monotonically increasing physical clock)
+ HLC mn (local clock value, hybrid clock)
+ VV mn (vector de HLC's com M entradas, local snapshot installed nesse server)
+ lst mn (local DC lst)
+ rst mn (Local DC rst)
+ prepared transactions (ja propos commit mas ainda nao recebeu valor)
+ commited transactions (ja propos e ja recebeu valor)
operacoes
START
Cliente inicia a transacao ao conectar-se a um coordinator partition.
O cliente manda também o lst e o rst, cujo coordinator, se for caso disso
atualiza os seus próprios valores de lst e rst, para que o cliente
possa ter acesso a dados tão frescos como já viu até agora.
O coordinator gera então o snapshot visivel para T (o seu timestamp). O lst
fica
igual ao que já tinha. O rst ficará igual ao min(rst, lst-1). O rst
obrigatoriamente tem que ser mais baixinho que o lst para que a versao
sempre mais fresca para o cliente vá ver seja a que ele vai escrever mas ainda não
escreveu e pode
ler na sua client cache.
Depois de definir o snapshot visivel. O Coordinator também
gera um identificador único para a transação, aquele que o item guarda.
Coloca T numa private Data structure sua.
Apos receber o reply c atualiza o lst e o rst e retira da
cache qualquer versao com timestamp menor que lst. É garantido ao
cliente que ele pode fazer isto, uma vez que o servidor garantiu que
se houver uma X.ct > lst então a versão que ele vai ler é da cache e
não uma possível remota.
READ
O cliente fornece a serie de keys que quer ler.
Para cada key, para ler, o cliente vai procurar na write-set, read-set
e depois na client cache, por esta ordem. Se um item correspondente a k
é encontrado então é adicionado à série de items para retornar,
assegurando assim o read-your-own-writes e repeatable-reads.
(ele vai ver a read-set porque se já leu um valor de k então vai ler
exatamente o mesmo agora)
Reads que nao possam ser served locally sao enviadas em paralelo
para as particoes correspondentes em conjunto com o snapshot.
Ao receber um read um server atualiza o seu rst e lst se forem
mais pequenos que os do cliente. O server retorna ao cliente, para cadda
k, a versao, dentro do snapshot, mais alta que tiver. Este valor vai
para a read-set.
WRITE
O cliente localmente da buffer dos writes para o seu write-set WSc.
Se uma k que tá a ser escrita já lá estiver então é atualizada, cc
então é inserida.
COMMIT
O cliente manda um commit request para o coordinator com o conteudo
da WSc, o id da transação e o timestamp do commit da sua ultima
transação.
O coordinator vai contactar todos os servidores que estejam
envolvidos com essa data (os cohorts) e manda-lhe o respetivo pedido
de commit.
As particoes (cohorts) vao atualizar os seus HLCs, propor o
commit timestamp e adicionar a transacao a pending list. Para refletir
causalidade os proposed timestamps sao maiores que o timestamp do
pedido e também que o seu hwtc (last transaction commited timestamp)
O coordinator depois escolhe o valor mais alto para tal.
Manda o bicho para todas as partições, limpa o contexto atual. Envia
o commit timestamp para o cliente
BiST
Periodicamente, as particoes dentro de uma DC trocam os seus version
vectors. O lst é computado como o minimo das local entries. O rst é
computado com o minimo das remotes. As particoes dentro de uma DC
são organizadas em árvore para reduzir os custos de comunicação.
Garbage Collection
periodicamente as particoes dentro de uma Dc trocam o snapshot (visivel
a uma transacao ativa) mais antigo. É calculado o minimo destes valores
para determinar o snapshot mais antigo que ainda é Necessário.
Todas as partições vão fazer um scan as suas keys mantendo
apenas as versoes >= que este timestamp mais antigo, tudo o resto pode
ser eliminado. Porque já não é utilizado para fazer uma transação.
Correctness
Snapshots são causais
Para começar uma transação o cliente dá piggy-back ao seu freshest
snapshot que já viu, para garantir a monoticidade do snapshot visto
por c.
Os commit timestamps refletem a causalidade e o BiST mantem
um lower bound do snapshot instalado por cada particao numa DC.
Se uma chave X está dentro do snapshot de uma transação, então
as suas dependências também estarão, porque:
+ as dependências geradas na mesma DC onde X foi criado tem um
timestamp menor que X
+ dependências geradas numa Remote DC também têm timestamp menor que
o de X.
On top of do spanshot dado pelo coordinator, o cliente aplica
os writes que não estão no snapshot. Estes writes não podem depender
em items criados por outros clientes que estão fora do snapshot visivel
por c. (pode alterar o resultado mas não depender)
como é que ao meter rst = lst -1 garante que não há versão nenhuma maior do
outro lado?
Eu acho que não garante, apenas faz com que ele leia a que vai escrever e não
a outra.