Autor: Chen Jinjian
blog pessoal: HTTPS: //jian1098.github.io
CSDN blog: https: //blog.csdn.net/c_jian
Jane book: https: //www.jianshu.com/u/8ba9ac5706b6
Contato: jian1098 @ qq.com
Sobre etcd
Introdução
etcd
É um sistema de armazenamento de valor-chave distribuído de código aberto e altamente disponível, desenvolvido com a linguagem Go, que pode ser usado para configurar o compartilhamento e o registro e a descoberta de serviços.
Características
- Replicação completa: cada nó do cluster pode usar o arquivo completo
- Alta disponibilidade: Etcd pode ser usado para evitar pontos únicos de falha de hardware ou problemas de rede
- Consistência: cada leitura retornará a gravação mais recente em vários hosts
- Simples: inclui uma API bem definida e orientada ao usuário (gRPC)
- Segurança: Implementado TLS automatizado com autenticação de certificado de cliente opcional
- Rápido: velocidade de referência de 10.000 gravações por segundo
- Confiável: o algoritmo Raft é usado para obter um catálogo de armazenamento de serviço altamente consistente e disponível
Grupo
Como um sistema de armazenamento de valores-chave de alta disponibilidade, o etcd é inerentemente projetado para clustering. Como o algoritmo Raft requer uma maioria de nós para votar ao tomar decisões, o etcd geralmente recomenda um número ímpar de nós para implantação de cluster, e o número recomendado é 3, 5 ou 7 nós para formar um cluster.
Descoberta de serviço
A descoberta de serviço visa resolver um dos problemas mais comuns em sistemas distribuídos, ou seja, como os processos ou serviços no mesmo cluster distribuído podem se encontrar e estabelecer uma conexão. Essencialmente, a descoberta de serviço é saber se há processos no cluster escutando nas portas udp ou tcp, e você pode localizar e conectar pelo nome. Para resolver o problema de descoberta de serviço, os três seguintes pilares são necessários, nenhum dos quais é indispensável
-
Catálogo de armazenamento de serviço altamente consistente e disponível. Etcd baseado no algoritmo Raft é um diretório de armazenamento de serviço altamente consistente e disponível.
-
Um mecanismo para registrar serviços e monitorar o estado de saúde dos serviços. Os usuários podem registrar serviços no etcd, definir os serviços registrados e
key TTL
manter a pulsação do serviço regularmente para obter o efeito de monitorar o status de integridade. -
Um mecanismo para localizar e conectar serviços. Os serviços registrados sob o assunto especificado por etcd (catálogo de serviços composto de nomes de serviços) também podem ser encontrados no assunto correspondente.
Componentes do núcleo
-
Servidor HTTP: usado para processar solicitações de API enviadas por usuários e solicitações de sincronização e informações de pulsação de outros nós etcd.
-
Armazenar: Usado para processar várias funções suportadas pelo etcd, incluindo indexação de dados, mudanças de status de nó, monitoramento e feedback, processamento e execução de eventos, etc. É a implementação específica da maioria das funções de API fornecidas pelos usuários pelo etcd.
-
Jangada: A implementação específica do algoritmo de consistência forte de Jangada é o núcleo do etcd.
-
WAL: O registro de gravação antecipada é o método de armazenamento de dados do etcd. Além de armazenar o estado de todos os dados na memória e o índice do nó, o etcd usa o WAL para armazenamento persistente. No WAL, todos os dados serão registrados antecipadamente antes do envio. Instantâneo é um instantâneo de estado obtido para evitar dados excessivos; a entrada representa o conteúdo de log específico armazenado.
Instale o etcd
A partir do https://github.com/etcd-io/etcd/releases
download da última versão, descompacte etcd
e descompacte etcdctl
dois programas (linux e windows iguais). Entre eles etcd
está o arquivo binário que executa o serviço etcd, que etcdctl
é o cliente etcd da linha de comando oficial, que etcdctl
pode ser usado para acessar o serviço etcd na linha de comando.
Para facilitar a operação, os dois arquivos podem ser adicionados à variável de ambiente do sistema por soft link
ln -fs /root/eosio/2.0/bin/etcd /usr/local/bin/etcd
ln -fs /root/eosio/2.0/bin/etcdctl /usr/local/bin/etcdctl
Ver versão
etcd --version
Inicie o etcd
etcd
Parâmetros opcionais:
-name
Nome do nó, o padrão é UUID
-data-dir
O diretório onde os logs e instantâneos são salvos, o padrão é o diretório de trabalho atual
-addr
O endereço IP publicado e a porta. O padrão é 127.0.0.1:2379
-bind-addr
O endereço de escuta usado para conexões de cliente, o padrão é a configuração -addr
-peers
Uma lista separada por vírgulas de membros do cluster, por exemplo, 127.0.0.1:2380,127.0.0.1:2381
-peer-addr
O endereço IP publicado da comunicação do serviço de cluster, o padrão é 127.0.0.1:2380.
-peer-bind-addr
O endereço de escuta da comunicação do serviço de cluster, o padrão é a configuração -peer-addr
A configuração acima também pode definir o arquivo de configuração, o padrão éetcd目录/etcd.conf
Operações de biblioteca de valor-chave
写 (colocar)
etcdctl put name "hello world" //新增和更新都是put
Ler (obter)
etcdctl get name
Consulta por prefixo
etcdctl get name --prefix //查找前缀为name的
Excluir (del)
etcdctl del name
Transação (txn)
As transações no etcd são executadas atomicamente e suportam apenas expressões como if ... then ... else ...
//先赋值
etcdctl put user1 bad
//开启事务
etcdctl txn --interactive
compares:
// 输入以下内容,注意=号两边要有空格,输入结束按两次回车
value("user1") = "bad"
//如果 user1 = bad,则执行 get user1
success requests (get, put, del):
get user1
//如果 user1 != bad,则执行 put user1 good
failure requests (get, put, del):
put user1 good
// 运行结果,执行 success
SUCCESS
user1
bad
Assistir
// 当 stock1 的数值改变( put 方法)的时候,watch 会收到通知,在这之前进程会阻塞
$ etcdctl watch stock1
// 新打开终端etcd 多台服务器集群
$ export ETCDCTL_API=3
$ etcdctl put stock1 1000
//在watch 终端显示
PUT
stock1
1000
$ etcdctl watch stock --prefix
$ etcdctl put stock1 10
$ etcdctl put stock2 20
Alugar
O lease pode definir o tempo de expiração do acesso
$ etcdctl lease grant 300 //创建一个300秒的租约
# lease 326963a02758b527 granted with TTL(300s)
$ etcdctl put sample value -- lease=326963a02758b527 //写入操作时将租约id为326963a02758b527的租约分配给sample
OK
$ etcdctl get sample
$ etcdctl lease keep-alive 326963a02758b520 //续约
$ etcdctl lease revoke 326963a02758b527 //手动释放租约
lease 326963a02758b527 revoked
# or after 300 seconds //自动释放租约
$ etcdctl get sample
O lease oferece várias funções:
- Concessão: Atribuir um contrato de arrendamento.
- Revogar: Liberar um contrato de arrendamento.
- TimeToLive: obtenha o tempo TTL restante.
- Locações: liste todas as locações no etcd.
- KeepAlive: Renove automaticamente um contrato de arrendamento em um horário fixo.
- KeepAliveOnce: Renove uma concessão uma vez.
- Fechar: Parece que está fechando todas as locações estabelecidas pelo cliente atual.
Bloqueio distribuído (bloqueio)
Bloqueio distribuído, quando uma pessoa opera, a outra só pode ver, mas não operar
# 第一终端
$ etcdctl lock mutex1
mutex1/326963a02758b52d
# 第二终端
$ etcdctl lock mutex1
# 当第一个终端结束了,第二个终端会显示
mutex1/326963a02758b53
Eleição
O nó de eleição é o líder, apenas o nó líder tem permissão de gravação e o nó comum só tem permissão de leitura para garantir a consistência dos dados; o nó líder enviará periodicamente batimentos cardíacos para os nós comuns, e o novo líder será eleito automaticamente quando os nós comuns não podem receber a pulsação
$ etcdctl elect one p1
one/326963a02758b539
p1
# another client with the same name blocks
$ etcdctl elect one p2
//结束第一终端,第二终端显示
one/326963a02758b53e
p2
Monitoramento de status de cluster (endpoint)
Verificação de integridade do cluster
$ etcdctl --write-out=table endpoint status
$ etcdctl endpoint health
Instantâneo
Usado para salvar instantâneos do banco de dados etcd
etcdctl snapshot save my.db
Snapshot saved at my.db
etcdctl --write-out=table snapshot status my.db
Gestão de membros do cluster (Membro)
Usado para visualizar, adicionar, excluir, atualizar membros
export ENDPOINTS=127.0.0.1:2379,127.0.0.1:2479,127.0.0.1:2579 //windows下export换成set
etcdctl member list -w table //成员列表-w可省略
etcdctl --endpoints=$ENDPOINTS member remove b9057cfdc8ff17ce //删除成员
etcdctl --endpoints=$ENDPOINTS member add cd3 --peer-urls=http://127.0.0.1:2180 //添加成员cd3为成员名
Iniciar novo nó
etcd --name cd3 --listen-client-urls http://127.0.0.1:2179 --advertise-client-urls http://127.0.0.1:2179 --listen-peer-urls http://127.0.0.1:2180 --initial-advertise-peer-urls http://127.0.0.1:2180 --initial-cluster-state existing --initial-cluster cd2=http://127.0.0.1:2580,cd0=http://127.0.0.1:2380,cd3=http://127.0.0.1:2180,cd1=http://127.0.0.1:2480 --initial-cluster-token etcd-cluster-1
Go language operation etcd
conexão
Baixe o pacote de driver
go get github.com/coreos/etcd/clientv3
Serviço de conexão
cli, err := clientv3.New(clientv3.Config{
Endpoints: []string{
"localhost:2379"},
// Endpoints: []string{"localhost:2379", "localhost:22379", "localhost:32379"}
DialTimeout: 5 * time.Second,
})
Leia e escreva
Escreva
O primeiro parâmetro é goroutine
o contexto Context
e os próximos dois parâmetros são chave e valor.
kv := clientv3.NewKV(cli)
putResp, err := kv.Put(context.TODO(),"/test/key1", "Hello etcd!")
// PutResp: &{cluster_id:14841639068965178418 member_id:10276657743932975437 revision:3 raft_term:7 <nil>}
Consulta geral
getResp, err := kv.Get(context.TODO(), "/test/key1")
Voltar à estrutura
type RangeResponse struct {
Header *ResponseHeader `protobuf:"bytes,1,opt,name=header" json:"header,omitempty"`
// kvs is the list of key-value pairs matched by the range request.
// kvs is empty when count is requested.
Kvs []*mvccpb.KeyValue `protobuf:"bytes,2,rep,name=kvs" json:"kvs,omitempty"`
// more indicates if there are more keys to return in the requested range.
More bool `protobuf:"varint,3,opt,name=more,proto3" json:"more,omitempty"`
// count is set to the number of keys within the range when requested.
Count int64 `protobuf:"varint,4,opt,name=count,proto3" json:"count,omitempty"`
}
O campo Kvs salva todos os pares kv encontrados neste Get. Como o exemplo acima só obtém uma única chave, você só precisa julgar se len (Kvs) é igual a 1 para saber se a chave existe.
Pesquisa por prefixo
rangeResp, err := kv.Get(context.TODO(), "/test/", clientv3.WithPrefix())
Consulta de paginação
RangeResponse.More
E funcionará Count
quando usarmos withLimit()
outras opções para prosseguir Get
, o que é equivalente à consulta de virada de página.
operação op
Op significa literalmente "operação". Tanto Get quanto Put pertencem a Op, que são apenas APIs especiais abertas para simplificar o desenvolvimento do usuário.
O parâmetro Op é uma operação abstrata, que pode ser Put / Get / Delete ...; e OpResponse é um resultado abstrato, que pode ser PutResponse / GetResponse ...
O Op pode ser criado por alguns métodos definidos no Cliente:
- função OpDelete (key string, opts… OpOption) Op
- função OpGet (key string, opts… OpOption) Op
- função OpPut (key, val string, opts… OpOption) Op
- função OpTxn (cmps [] Cmp, thenOps [] On, elseOps [] On) On
Na verdade, não é diferente de chamar KV.Put e KV.GET diretamente.
cli, err := clientv3.New(clientv3.Config{
Endpoints: endpoints,
DialTimeout: dialTimeout,
})
if err != nil {
log.Fatal(err)
}
defer cli.Close()
ops := []clientv3.Op{
clientv3.OpPut("put-key", "123"),
clientv3.OpGet("put-key"),
clientv3.OpPut("put-key", "456")}
for _, op := range ops {
if _, err := cli.Do(context.TODO(), op); err != nil {
log.Fatal(err)
}
}
alugar
Crie um contrato de arrendamento
grantResp, err := lease.Grant(context.TODO(), 10)
Atribuir arrendamento
kv.Put(context.TODO(), "/test/vanish", "vanish in 10s", clientv3.WithLease(grantResp.ID))
Se o Lease tiver expirado antes do Put, essa operação Put retornará um erro e você precisará reatribuir o Lease neste momento
Renovar
keepResp, err := lease.KeepAliveOnce(context.TODO(), grantResp.ID)
Se o aluguel expirou antes da execução, ele precisa ser realocado. etcd não fornece uma API para implementar Put with Lease atômico, precisamos julgar err para realocar o Lease.
romances
txn := kv.Txn(context.TODO())
kv.Txn(context.TODO()).If(
clientv3.Compare(clientv3.Value(k1), ">", v1),
clientv3.Compare(clientv3.Version(k1), "=", 2)
).Then(
clientv3.OpPut(k2,v2), clentv3.OpPut(k3,v3)
).Else(
clientv3.OpPut(k4,v4), clientv3.OpPut(k5,v5)
).Commit()
Semelhante a clientv3.Value () \ usado para especificar atributos-chave, existem vários métodos:
- função CreateRevision (key string) Cmp: A versão de criação de key = xxx deve atender ...
- função LeaseValue (key string) Cmp: Lease ID com chave = xxx deve satisfazer ...
- func ModRevision (key string) Cmp: A última versão modificada de key = xxx deve atender ...
- func Value (string de chave) Cmp: O valor de criação de key = xxx deve satisfazer ...
- func Version (key string) Cmp: Os tempos de atualização cumulativos de key = xxx devem atender ...
monitor
Watch é usado para monitorar as mudanças de uma determinada chave Watch
e retorna uma após a chamada WatchChan
. Seu tipo é declarado da seguinte maneira:
type WatchChan <-chan WatchResponse
type WatchResponse struct {
Header pb.ResponseHeader
Events []*Event
CompactRevision int64
Canceled bool
Created bool
}
Artigo de referência
https://juejin.im/post/5dba5bedf265da4d461eb8ff#heading-3
https://zhuanlan.zhihu.com/p/38300827