Redis and
NATS Streaming
Índice
- Sistema monolítico vs distribuído
- Troca de dados
- Brokers
- NATS
- Bancos de Dados
- SQL vs No-SQL
- Redis
- Conclusão e Referências
Sistema Monolítico
- Várias threads
- Variáveis globais
- Um único BD
Desvantagens:
- Difícil de versionar
- Compartilhamento de recursos
Sistema
BD
Sistema distribuído
- Contêineres Docker
- Uso de recursos distintos
Conexão entre contêineres:
- Identificação de cada parte para comunicação
- Topologia de comunicação fixa
Comunicação Síncrona
- Ideal para comunicação externa ( e. g. GraphQL, REST, etc)
- Comunicação interna síncrona = sistema acoplado
- Cascata de falhas
Comunicação Assíncrona
- Sem necessidade de resposta imediada
- Sistema desacoplado
- Maior flexibilidade para cada parte responder a comunicação
Sistemas de Mensageria (Brokers)
- Toda comunicação interna passa pelo broker
- Mensagens são publicadas em canais
- Cada contêiner se inscreve a certos canais
Vantagens:
- Facilita a comunicação de contêineres
- Facilita a inclusão de novos contêineres
Exemplos de Brokers:
- Apache Kafka, Rabbitmq, NATS Streaming, etc.
NATS Streaming
- Perimite o armazenamento das mensagens em disco
- Clientes em várias linguagens
- Fácil de usar
- Baixa latência e alta vazão de mensagens
Comparação de vazão com outros brokers
Comparação de latência com outros brokers
Broker | Latência* |
---|---|
Apache Kafka | ~1600,000 ms |
Rabbitmq | ~500,000 ms |
Kestrel | ~220.000 ms |
NSD | ~70,000 ms |
NATS-ruby | ~0,540 ms |
NATS | ~0,325 ms |
* Latência para 1.000.000 mensagens
fonte: https://bravenewgeek.com/dissecting-message-queues/
Uso do NATS Streaming
const NATS = require('node-nats-streaming');
const stan = NATS.connect('test-cluster', 'test', { // abrindo conexão
url: process.env.NATS_URL
});
stan.on('connect', async () => { // publicando mensagem
setTimeout(() => {
stan.publish('new.user', '42', (err, guid) => {
if (err) console.log("Failed publishing");
else console.log(`published with guid: ${guid}`);
});
}, 5000);
});
// subscrevendo a canal
stan.on('connect', async () => {
const optsAll = stan.subscriptionOptions().setDeliverAllAvailable();
const new_user_subs = await stan.subscribe('new.user', optsAll);
const user_ids_subs = {};
new_user_subs.on('message', async (msg) => {
console.log(`'new.user': ${msg.getData()}`);
const uid = Number.parseInt(msg.getData());
user_ids_subs[uid] = await stan.subscribe(`user.${uid}`, optsAll);
user_ids_subs[uid].on('message', async (msg) => {
'do something'
});
});
});
Acesso aos Dados
- Broker =/= BD compartilhado
- Sem necessidade consultas constantes para entrada de novos dados
- Como diminuir o número de acessos?
Um Banco de Dados por Contêiner
Modelagem de BD
Bancos de Dados SQL
- PostgreSQL, MariaDB, SQlite
- Linguagem SQL
- Consultas diversas
Desvantagens:
- Alta latência
- Difícil reestruturação do modelo
SELECT Nome_Artista,Nome
FROM Artista A,Usuário_Titular S,Escuta E,Toca T,Usuário U
WHERE E.Usuário_ID = U.Usuário_ID
AND E.Música_ID = T.Música_ID
AND T.Artista_ID = A.Artista_ID
AND A.cidade = S.cidade
AND U.Usuário_ID = S.Usuário_ID;
SELECT Nome_Artista
FROM Artista,(SELECT DISTINCT Artista_ID,Lista_ID FROM Produz) AS P1
WHERE Artista.Artista_ID = P1.Artista_ID
AND NOT EXISTS (SELECT *
FROM Produz P2
WHERE P1.Lista_ID = P2.Lista_ID
AND P2.Artista_ID <> P1.Artista_ID)
AND EXISTS (SELECT *
FROM Compõe,Toca T1
WHERE Compõe.Música_ID = T1.Música_ID
AND P1.Lista_ID = Compõe.Lista_ID
AND NOT EXISTS (SELECT *
FROM Toca T2
WHERE T2.Música_ID = Compõe.Música_ID
AND T1.Artista_ID <> T2.Artista_ID));
Propriedades ACID
-
Atomicidade
A transação deve ter todas as suas operações executadas em caso de sucesso ou, em caso de falha, nenhum resultado de alguma operação refletido sobre a base de dados. -
Consistência
A transação deve respeitar as regras de integridade dos dados -
Isolamento
Cada transação só é efetuada depois que a anterior já ocorreu. -
Durabilidade
O resultado de todas transações executadas com sucesso é armazenado em disco.
BDs No-SQL
- sem linguagem expressiva para consulta de dados
- permitem que entidades armazenem um número variável de atributos.
- (e. g. MongoDB, REDIS, Cassandra)
Vantagens:
- Menor latência e maior vazão
- Facilmente particionados
Propriedades BASE
-
Básica disponibilidade
O Banco de Dados está disponível na maior parte do tempo - Estado maleável
As transações de escrita não tem garantia que serão feitas instantaneamente e que as replicas do BD terão os mesmo estado ao mesmo tempo. - Eventual consistência
Em algum tempo, todos os dados, em todas as réplicas, terão o mesmo valor (e. g. quando uma leitura for feita)
Comparação entre diferentes SGBDs
[Rabl T, 2012]
Comparação entre diferentes SGBDs
[Rabl T, 2012]
Redis
- Remote Dictionary Server
- BD Chave-Valor
- Baixa latência devido ao funcionamento em memória RAM
- Possibilita armazenamento em disco para backup
- Clientes em várias linguagens
- Comandos de fácil uso
Tipos de Armazenamentos
Strings
redis-cli
redis> SET mykey "Hello"
"OK"
redis> GET mykey
"Hello"
redis> MSET key1 "Hello" key2 "World"
"OK"
redis> MGET key1 key2 nonexisting
1) "Hello"
2) "World"
3) (nil)
Tipos de Armazenamentos
Strings
redis> GET mykey
"Hello"
redis> STRLEN mykey
(integer) 5
redis> APPEND mykey " World"
(integer) 11
redis> SETRANGE mykey 6 "Redis"
(integer) 11
redis> GET mykey
"Hello Redis"
Tipos de Armazenamentos
Strings
redis> SET mykey "10"
"OK"
redis> INCR mykey
(integer) 11
redis> DECR mykey
(integer) 10
redis> INCRBY mykey 5
(integer) 15
redis> GET mykey
"11"
redis> SET myfloat 10.50
"OK"
redis> INCRBYFLOAT myfloat 0.1
"10.6"
Tipos de Armazenamentos
Chaves
redis> SET key1 "Hello"
"OK"
redis> EXISTS key1
(integer) 1
redis> EXISTS nosuchkey
(integer) 0
redis> TYPE key1
"string"
redis> DEL key1 key2 key3
(integer) 2
Tipos de Armazenamentos
Sets
redis> SADD myset "Hello"
(integer) 1
redis> SADD myset "World"
(integer) 1
redis> SADD myset "World"
(integer) 0
redis> SMEMBERS myset
1) "World"
2) "Hello"
redis> SISMEMBER myset "Hello"
(integer) 1
redis> SCARD myset
(integer) 2
Tipos de Armazenamentos
Sets
redis> SMEMBERS myset
1) "World"
2) "Hello"
redis> SADD myotherset "Hello" "there"
(integer) 1
redis> SINTER myset myotherset
1) "Hello"
redis> SDIFF myset myotherset
1) "World"
Tipos de Armazenamentos
Sorted Sets
redis> ZADD myzset 1 "one" 2 "two" 3 "three"
(integer) 3
redis> ZADD myzset 1 "uno"
(integer) 1
redis> ZRANGE myzset 0 -1 WITHSCORES
1) "one"
2) "1"
3) "uno"
4) "1"
5) "two"
6) "2"
7) "three"
8) "3"
redis> ZRANGE myzset 2 3
1) "three"
Tipos de Armazenamentos
(Linked) Lists
redis> RPUSH mylist "one"
(integer) 1
redis> RPUSH mylist "two"
(integer) 2
redis> RPUSH mylist "three"
(integer) 3
redis> RPOP mylist
"three"
redis> LRANGE mylist 0 -1
1) "one"
2) "two"
redis> LPOP mylist
"one"
redis> LRANGE mylist 0 -1
1) "two"
Tipos de Armazenamentos
Hashes
redis> HMSET myhash field1 "Hello" field2 "World"
"OK"
redis> HMGET myhash field1 field2 nofield
1) "Hello"
2) "World"
3) (nil)
redis> HKEYS myhash
1) "field1"
2) "field2"
redis> HGETALL myhash
1) "field1"
2) "Hello"
3) "field2"
4) "World"
Modelo Conceitual
Modelo Entidade Relacionamento
Modelo
Físico
- SQL: Linguagem SQL
- Chave-Valor: o BD não tem implementação do modelo antes da entrada de dados.
O usuário escolhe seguir o modelo
- SQL: Necessita definir chaves primárias, atributos, chaves estrangeiras, etc.
- Chave-Valor: Cada atributo tem uma chave
- recomenda-se usar chaves do formato "Id_Entidade:Nome_atributo"
(e. g. "84EC29A:Endereço" )
Modelo Lógico
Melhores Casos de uso de SGBDs Chave-Valor
- Sistemas onde as consultas já são conhecidas previamente
- Necessidade de baixa latência
Melhores práticas
- Trocar Leitura e Escrita por comandos específicos
(e. g. INCR ) - Armazenar atributos que são sempre processados juntos na mesma chave
Redis e
NATS Streaming
em Conjunto
Redis
Os dados que cada contêiner precisa consultar para fazer suas operações são armazenados em instâncias distintas do redis
Uma para cada contêiner
NATS Streaming
Qualquer ação realizada por um contêiner que afeta o resto do sistema gera um evento que é enviado para o broker.
Uma única instância do broker administra o envio e recebimento de todo o sistema
Orquestração
- Um microsserviço principal envia comandos para o resto do sistema
- Outros microsserviços só realizam ações quando requisitado
- sistema mais acoplado, maior suscetível a cascata de falhas
Coreografia
- Todos os microsserviços recebem eventos
- Cada microsserviço responde ao evento de maneira diferente
- sistema mais independente, com maior tolerância a falhas locais
Estilos de Organização de Microsserviços
Arquitetura de Microsserviços Reativa
- Organizada baseada em Coreografia
- Uso de Broker para envio e recebimento de eventos
- Uso de BD local para acesso fácil e rápido a dados mais utilizados
- Cada ação no sistema gera um evento
- Cada serviço escolhe processar ( ou não ) esse evento de forma distinta
- Dados essenciais para cada microsserviço armazenados em um BD de baixa latência
Referencias
Solving big data challenges for enterprise application performance management (2012)
Rabl T, Gómez-Villamor S, Sadoghi M, Muntés-Mulero V, Jacobsen H, Mankovskii S
Dissecting Message Queues - 2014, Tyler Treat - https://bravenewgeek.com/dissecting-message-queues/
Guias?,Tutoriais?
redis.io/commands
nats.io
Fim
fernando.scattone@usp.br
Gitlab - @fernandofreire
Redis and NATS streaming
By Fernando Freire Scattone
Redis and NATS streaming
- 623