DevSecOps

19 dez, 2018

Redis + Redundância com Sentinel + Docker

Publicidade

Neste artigo vamos abordar os principais conceitos do Redis: sua utilização, alguns comandos de manipulação de valores em memória e utilização do Redis com sentinel – tudo dentro de diversos dockers.

Cobrirei desde a montagem da imagem, ferramentas necessárias, até a configuração e implementação de vários redis (Master-Slave) junto de dois sentinels e mostrarei na prática como os slaves e o sentinel trabalham com redundância.

O que é o Redis?

Redis é um banco de dados não relacional que tem dentro de sua estrutura o armazenamento chave-valor. Ele oferece diversas estruturas de armazenamento de dados na memória, o que faz com que possamos ter diversos formatos na chave-valor, podendo ser: hashes , list, sets, strings.

Além disso, o Redis oferece varias funcionalidades para trabalhar com essa chave-valor para comparar, buscar ou manipular os valores, e como isso está tudo em memória, ele acaba sendo uma opção extremamente rápida para trabalhar com dados.

Outro ponto importante a salientar é que o Redis executa seus comandos de forma atômica, ou seja, o mesmo trabalha de forma single-threaded. Desta forma, somente um comando é executado por vez.

Diante disso, temos que considerar alguns pontos sobre o Redis para validar em qual cenário melhor se enquadra sua usabilidade:

  • Não é um banco de dados para armazenar dados por um longe período, por mais que o Redis possui recursos para isso
  • Não deve ser utilizado para substituir um banco de dados relacional
  • Não possui suporte oficial para Windows
  • Por ser em memória, não se pode armazenar muitos dados

Vantagens do Redis

O Redis emprega um estilo de master/slave, o que torna a replicação assíncrona entre os servidores subordinados ao master, e dessa forma temos um ganho de leitura muito grande.

Em casos de queda em um dos servidores e houver uma possibilidade de perda de informação, no redis podemos habilitar em suas configurações um time para um snapshots do cenário atual do armazenamento e escrever em um AOF – Append Only File das alterações realizadas. Isso nos permite uma rápida restauração dos dados.

Por ser código aberto, tempos uma grande vantagem de ser compatível com diversas linguagens, sendo algumas delas: C#, C++, Javascript, Node.js, Ruby, Go, Java, PHP e etc.

Imagine que você tem uma etapa de sua aplicação que precisa buscar algumas informações no banco de dados relacional. A tabela possui cerca de 100 registros e essas informações têm pouca DML (mudança nos dados).

Agora imagine que essa sua aplicação hoje possui conexão de em média 15 usuários utilizando esse recurso que consulta essa tabela, e depois de dois anos essa sua aplicação agora possui 1000 usuários. Por que não buscar esses 100 registros no Redis ao invés de gastar recurso do banco de dados relacional?

Instalação do Redis

O Redis possui suporte oficial para Mac e Linux, e existe uma versão para Windows criada pela comunidade, mas não é oficial.

Neste artigo, conforme dito anteriormente, realizaremos a instalação via Docker. Para outras informações sobre o download do Redis, basta acessar o link:

Rapidamente sobre Docker

O Docker é uma plataforma de software de código aberto para criar, implantar e gerenciar contêineres de aplicativos virtualizados em um sistema operacional (SO) comum.

Com um ecossistema de ferramentas aliadas, ele que empacota, provisiona e executa contêineres independentemente do sistema operacional.

O Docker pode ser baixado através do link:

Neste artigo estou utilizando o Docker no Windows.

Subindo um container, instalando recursos necessários e o Redis

Com o nosso Docker funcionando, vamos abrir o terminal e baixar uma imagem do repositório docker do Ubuntu – S.O Linux que será utilizado neste artigo.

Estou utilizando como terminal, o software ConEmu, mas fica à sua preferência. Para quem tiver interesse, o ConEmu é gratuito e tem algumas vantagens: podemos visualizar em tela cheia, deixar transparente, alterar fontes, cores e etc. D

Executando o comando: “docker images” para validar se o Docker está rodando corretamente:

Em seguida, vamos baixar a ultima versão do Ubuntu disponível no repositório:

Validando se o download da imagem foi feito com sucesso:

Feito isso, executaremos “docker run [IMAGE ID]” a partir da imagem com o parâmetro -d para execução em segundo plano do container (sem a necessidade de ficar conectado):

Se não ocorrer nenhum erro, o retorno deverá ser o seguinte ao executar um “docker ps” para listar os containers ativos:

Agora acessaremos o container através do comando “docker exec -it [ID CONTAINER] bash“, onde utilizamos o parâmetro -it para acessar mais de uma sessão do mesmo host:

Vamos agora atualizar nosso Ubuntu, instalar alguns recursos ausentes e em seguida, o Redis:

  • apt-get update:

  • apt-get install sudo:

  • apt-get install redis-server:

Testando instalação do redis:

Com o Redis rodando, vamos conhecer um pouco mais sobre o redis.conf, que é o arquivo de configuração do Redis:

/etc/redis/redis.conf

Para manipulação de arquivos vou instalar um pacote no Ubuntu chamado, nano que é um editor de texto em terminal simples:

apt-get install nano

nano redis.conf

Também existe outra forma de acessarmos a configuração do redis via comando, onde podemos obter o valor da configuração a partir de seu nome ou todas as configurações:

Com Dockerfile

Essa configuração do docker com Redis e demais utilidades podem ser facilmente iniciadas com docker file. Para isso, basta criar um arquivo Dockerfile (sem extensão) com as seguintes informações:

Salvar em um diretório de sua preferencia, navegar até a pasta onde se encontra presente o arquivo ou executar o comando a seguir com todo o caminho do arquivo:


docker build para informar a construção de uma imagem, -t para informar uma “assinatura” dessa imagem e o diretório do docker file, que neste caso é o diretório atual, então é informado ponto. A partir da execução, será iniciada a montagem da imagem de acordo com o sistema operacional e demais comandos:

Manipulando chave e valores com os cinco tipos

Iniciaremos pelo tipo mais básico de chave no Redis. Acessando o Redis com “redis-cli” vamos definir uma chave string simples:

Definindo com espaço:

Definindo uma chave string composta:

Listando as chaves:

Fazendo querying na busca das chaves:

Configurando a replicação de Master e Slave

Depois de brincarmos um pouco com os comandos básicos do Redis, vamos agora iniciar o setup do nosso redis para replicação. O Redis usa, por padrão, a replicação assíncrona, que tem baixa latência e alto desempenho. É o modo de replicação natural para a grande maioria dos casos de uso do Redis. A forma de replicação do Master para slave (líder seguidor) tem algumas características principais que devem ser abordadas:

1 – Quando iniciamos uma instância master (ou mestre) junto com seus escravos (slaves), é de responsabilidade do master manter atualizado os slaves de forma sincronizada sobre as atualizações dos dados (chaves, valores, expirações) afim de manter o “dataset” de ambos atualizado.

2 – Quando a instância do master é desligada por motivos imprevistos, por padrão o slave assume como master, e se existirem mais slaves, os demais slaves passam a receber os dados do novo master.

3 – Caso a comunicação entre um master e um slave seja interrompida, o slave tentará fazer uma ressincronização com o master de forma parcial. Ou seja, recuperar o que foi perdido no momento da falha de sincronização e estabelecer novamente a sincronização.

4 – Se uma ressincronização parcial não for possível, ou seja, não conseguir recuperar os dados perdidos entre a falha da sincronização, neste caso vai ocorrer uma sincronização completa, onde o master carregará todos os dados de forma a enviar para os slaves novamente e manter ambos atualizados.

Uma dica bem interessante que pode ser realizada no quesito de persistência dos dados é configurar um dos slaves para persistir os dados em disco (modificando o redis.conf) através dos arquivos RDB. Dessa forma, você não terá uma perda de performance na leitura, visto que o master em sua configuração não realiza escrita, somente o slave.

Um único ponto de atenção neste caso, é que o master, por não possuir o RDB em sua configuração, caso ocorra uma queda do master, o mesmo inicializará novamente com os dados vazios e consequentemente sincronizará com os slaves que também terão o RDB atualizado.

Vamos iniciar a configuração do nosso primeiro slave. Para isso, navegue até a pasta:

/etc/redis

Agora realizamos a cópia do arquivo redis.conf para o nome redis-slave.conf:

Depois disso, sabemos que o Redis, por padrão, está configurado para a porta 6379. Com isso, editaremos nosso arquivo redis-slave.conf para a porta 6380 e iremos configurar nosso slaveof para indicar o ip e a porta do Redis master.

Alterando a porta do slave para 6380:

Pressionamos Ctrl + W para localizar as configurações do slaveof:

Após configurar a porta deste arquivo redis-slave para 6380 e configurar o slaveof, vamos configurar o sentinel.

O Sentinel nada mais é do que um “Redis” que monitora a saúde de outros Redis, de forma a decidir qual nó (slave) será o novo mestre em caso de possíveis inconsistências, e é por este recurso de monitoria que devem ter pelo menos três nós (slave) para evitar um possível “empate” entre mais de um slave para se tornar master ou na validação de dados.

Instalando o redis-sentinel:

Iremos agora no mesmo diretório do redis.conf e abriremos o arquivo sentinel.conf para configuração de alguns pontos básicos do sentinel. Em primeiro lugar vamos alterar o down-after-miliseconds para 10 segundos. Esse parâmetro indica quanto tempo será necessário para detectar a queda do master e o slave assumir como novo master:

Em seguida, vamos configurar qual é o ip + porta do master para o sentinel:

Repare que existe o numero 2 no final da porta. Esse numero indica o numero de sentinels que precisam concordar que aquele master está inativo.

Vamos mudar também a porta padrão do sentinel para 26380:

Feito isso, salvaremos esse arquivo e realizaremos uma copia do mesmo para o nome sentinel2.conf.

O próximo passo é copiar novamente o arquivo sentinel.conf, mas desta vez mudando apenas a porta para 26381 e, por fim, editar o arquivo sentinel.conf mudando a porta para 26379. Com isso ficamos desta forma:

  • 1. sentinel.conf – Porta 26379
  • 2. sentinel2.conf – Porta 26380
  • 3. sentinel3.conf – Porta 26381

Observação: todos devem estar com down-after-miliseconds para 10 segundos.

Agora vamos iniciar todos nossos redis individualmente por console para validarmos os sincronismos entre master/slave e os logs do sentinel. Primeiro iniciamos o redis master:

redis-server redis.conf

Executando no diretório /etc/redis:

Depois disso, executaremos o redis-slave:

redis-server redis-slave.conf

Reparem que já foi feita a sincronização entre o master e slave.

Agora vamos iniciar os três sentinels:

  • redis-sentinel sentinel.conf
  • redis-sentinel sentinel2.conf
  • redis-sentinel sentinel3.conf

Observação: cada aba do console será para um sentinel.

Para verificar se os sentinels estão em funcionamento, podemos executar o seguinte comando de verificação: redis-cli monitor. Com isso, será possível verificar que os sentinels realizam um ping para validar se o redis-server está em funcionamento:

Agora simularemos uma troca de master e slave derrubando a conexão do redis.conf. Para isso, fecharemos a sessão do redis-master (redis.conf)

Repare que o slave começou a informar o erro, enquanto o sentinel já identificou a queda do master:

Quando iniciamos novamente o redis de ip 6379, repare que houve o início da recuperação dos dados que foram persistidos em disco e o sincronismo parcial.

Portanto, neste artigo abordamos os conceitos básicos do Redis, bem como uma simulação de disponibilidade e redundância com o Redis. Existem muitas abordagens que pode sem feitas não só com o conceito do sentinel, mas com os chamados channels do Redis, que criam um canal de comunicação ou a utilização de alguns tipos de dados como as lists, Pub/sub e sorted list.