Hub de Eventos com Redis
Motivação
Utilizar o Redis para armazenar e recuperar dados em memória para um cenário real e, utilizar os recursos de PUBLISH e SUBSCRIBE para comunicar assincronamente mensagens entre cliente e servidor, criando assim, um Hub de eventos.
O que é o Redis?
Redis, http://redis.io/, é uma estrutura de dados na memória, categorizado como banco de dados não relacional – NOSQL (Not Only SQL). Ele oferece suporte a estruturas como strings, hashes, lists, sets, sorted sets com intervalos de consultas, bitmaps, hyperloglogs e geospatial indexes. Oferece replicação nativa, scripts lua, LRU eviction, transações e diferentes níveis de persistência em disco.
Instalando e configurando
Para iniciar nosso artigo, vamos precisar instalar e configurar o Redis conforme os passos abaixo:
- Instalar o chocolatey;
- Instalar o Redis 64-bit com o chocolatey;
- Instalar e configurar o Redis Desktop Manager;
- Iniciar o Redis Server.
1. Instalando o chocolatey
Chocolatey é um gerenciador de pacotes para o Windows ele permite a instalação, configuração e atualizações de programas através de linha de comando. Para instalar o chocolatey abra o cmd.exe ou o powershell.exe com privilégios administrativos, e execute os comandos abaixo:
- Instalando com o Cmd.exe
@powershell -NoProfile -ExecutionPolicy Bypass -Command “iex ((new-object net.webclient).DownloadString(‘https://chocolatey.org/install.ps1’))” && SET PATH=%PATH%;%ALLUSERSPROFILE%\chocolatey\bin |
- Instalando com o PowerShell.exe (Certifique-se que Get-ExecutionPolicy está pelo menos como RemoteSigned)
iex ((new-object net.webclient).DownloadString(‘https://chocolatey.org/install.ps1’)) |
- Instalando com o PowerShell v3+ (Certifique-se que Get-ExecutionPolicy está pelo menos como RemoteSigned)
iwr https://chocolatey.org/install.ps1 -UseBasicParsing | iex |
Caso tenha algum problema, pode encontrar maiores informações aqui (https://chocolatey.org/install)
2. Instalando o Redis com o chocolatey
Para instalar no Windows, vamos abrir o prompt escolhido para rodar o chocolatey, e digitar a linha abaixo.
C:\> choco install redis-64 |
Caso tenha algum problema, pode encontrar maiores informações aqui (https://chocolatey.org/packages/redis-64/)
3. Instalando o Redis Desktop Manager
Redis Desktop Manager é a ferramenta que iremos utilizar para verificar nossos registros no Redis.
A versão para Windows é encontrada no endereço: (https://redisdesktop.com/download).
Após baixar e instalar no padrão Windows. Next > Next > Finish. Temos esta tela.
Precisamos configurar o RDM para conectar no servidor do Redis local, iremos iniciar o server no próximo tópico. Mas já é possível deixar configurado o básico no nosso manager. Abaixo um exemplo simples de conexão local:
4. Iniciando o Redis Server
O chocolatey instala todos os programas na pasta C:\ProgramData\chocolatey\lib. Para iniciarmos o servidor redis, vamos acessar a pasta é encontrado na pasta C:\ProgramData\chocolatey\lib\redis-64 e executar o arquivo redis-server.exe.
Esta tela nos mostra que o server foi iniciado com sucesso.
Usando o armazenamento de memória do Redis
Nesse momento, vamos aprender a utilizar o básico de armazenamento com strings. Inserir, recuperar e deletar chaves no Redis, fazendo assim, um cache de chave/valor. Utilizando os comandos SET (inserir), GET (recuperar) e DEL (Deletar).
Existem outros comandos para manipulação de strings, porém neste momento vamos usar o básico para entender e resolver problemas reais. Todos os exemplos serão feitos no redis-cli.exe, que é o client do Redis no Windows e pode ser encontrado na mesma pasta onde está o redis-server.exe, C:\ProgramData\chocolatey\lib\redis-64.
Inserindo registro (SET)
Um bom exemplo para usar com o cache do Redis é quando você precisa usar um carrinho de compra em um e-commerce, ao adicionar os itens no carrinho, você pode adicionar os itens usando o Redis, vamos iniciar o redis-cli.exe e escrever o comando:
set caderno:hora-de-aventura 2000
127.0.0.1:6379> set caderno:hora-de-aventura 2000
OK
127.0.0.1:6379>
Após a execução do comando o Redis retorna um OK, isto quer dizer que o comando foi executado com sucesso e agora temos uma chave chamada “caderno:hora-de-aventura” com o valor “2000”, o valor passado representa R$ 20,00.
OBS .: Utilizar o “:” como delimitador de “namespace”, é bem comum no Redis, e após nosso comando, temos a seguinte imagem no RDM.
Você pode especificar para qual “banco” você quer enviar as informações, por padrão, o Redis põe no db0.
Ao lado da nossa chave, temos uma opção chamada TTL que quer dizer Time To Live. É o tempo para expirar a key, se quisermos inserir um registro com tempo para expirar podemos usar o SET com o comando EXPIRE, ou usar o SETEX [key] [tempo] “value”.
Expirando um registro usando Time To Live (TTL)
Quando usaríamos esse tempo para a chave expirar? Para não deixar um item no carrinho eternamente sem ação. Vamos então adicionar um outro produto no carrinho, porém desta vez, esse produto irá expirar em 180 segundos – 3 minutos.
127.0.0.1:6379> setex caderno:the-joker 180 2200
OK
127.0.0.1:6379>
Adicionamos um caderno, com nome “the joker” que irá expirar em 180 segundos.
Para mais informações do comando, visite: (http://redis.io/commands/setex).
Recuperando registros
Estamos fazendo nossos exemplos todos pelo console do redis, conseguimos visualizar o que estamos inserindo, utilizando o RDM, porém podemos visualizar com o próprio client do redis, utilizando o comando GET.
127.0.0.1:6379> get caderno:hora-de-aventura
“2000”
127.0.0.1:6379>
Recebemos o valor “2000” da chave “caderno:hora-de-aventura”.
Deletando registros
Se você não criou uma chave com TTL, ainda assim é possível deletar ela, quando não servir mais pra você, evitando assim deixar registros desnecessários no redis.
127.0.0.1:6379> del caderno:hora-de-aventura
(integer) 1
127.0.0.1:6379>
O resultado “(integer) 1” significa que 1 registro foi alterado com o comando executado.
Outras palavras
O Redis oferece muitos outros comandos para manipulação de registros, para uma lista completa e para outros testes, sugiro a leitura da lista de comandos no próprio site do Redis (http://redis.io/commands).
Usando PUBLISH/SUBSCRIBE para criar nosso Hub de eventos
Agora que vem a cereja do bolo do artigo, como usar o Redis com Subscribe. O que nada mais é que usá-lo como message broker (https://en.wikipedia.org/wiki/Message_broker).
A abordagem que será mostrada aqui, nada mais é que a mesma do padrão Observer – também conhecido como Dependents Publish-Subscribe –, o que esse padrão faz?
Basicamente ele representa uma relação de 1-N (de um para muitos) entre objetos. Assim, quando um objeto altera o seu estado os objetos dependentes serão notificados/informados/avisados e atualizados de forma automática. O padrão possibilita que objetos sejam avisados da mudança de estado de outros eventos ocorrendo em outro objeto.
Podemos dizer de forma simples que o objetivo principal do padrão Observer é manter a consistência entre objetos relacionados sem criar um código fortemente acoplado.
Então já revemos o que é o padrão Observer, agora é simples pegar essa ideia e utilizar no Redis, pois o subscribe tem a mesma ideia do Observer.
Para trabalhar com o PubSub do Redis, temos os comandos: psubscribe, publish, punsubscribe, subscribe e unsubscribe. Vamos utilizar o PSUBSCRIBE e o PUBLISH.
Uma boa observação sobre psubscribe e subscribe é que o primeiro assina um canal a partir de um padrão, isto quer dizer que, ele faz assinaturas genéricas, aceitando caracteres coringas para nomes de canais. Já o subscribe aceita apenas nomes fixos de canais.
E como poderíamos usar isto em um cenário real? Uma resposta à esta pergunta seria um newsletter. Você pode disponibilizar newsletters específicas em seu site para o visitante ficar por dentro das notícias que você publica. Música, tecnologias, animais, quaisquer outras áreas que seu site possa ter e seu visitante queira ficar por dentro.
Vamos fazer alguns exemplos baseando-se em uma história para ficar mais simples o entendimento.
Assinando canais específicos
Visitando alguns fóruns, encontrei um site muito legal e decidi assinar os newletters de música e tecnologia, mesmo o site tendo outras áreas interessantes como “GothamCity” eu decidi escolher apenas música e tecnologia.
No nosso console eu digito a linha abaixo para assinar o canal de música.
127.0.0.1:6379> subscribe musica
Reading messages… (press Ctrl-C to quit)
1) “subscribe”
2) “musica”
3) (integer) 1
Podemos notar que o redis-cli fica esperando alguma coisa, isto se dá ao fato de que o Redis usa comunicação TCP. O client enviou uma resposta para o server e está esperando a resposta, essa resposta virá quando alguém publicar (PUBLISH) no canal de “musica”. Uma clássica comunicação por sockets.
Também assino o canal de tecnologia.
127.0.0.1:6379> subscribe tecnologia
Reading messages… (press Ctrl-C to quit)
1) “subscribe”
2) “tecnologia”
3) (integer) 1
Com isso, eu estou esperando mensagens dos canais: “musica” e “tecnologia”, enquanto isso, soube que o Jack Napier começou a se interessar pela vida do Batman, então ele assinou o canal GothamCity para saber o que tem acontecido na cidade.
127.0.0.1:6379> subscribe gothamCity
Reading messages… (press Ctrl-C to quit)
1) “subscribe”
2) “gothamCity”
3) (integer) 1
Assinando todos os canais
Como esse nome não era estranho, descobri que Jack é o alter ego do Coringa e com isso descobri que ele não se contentou em ficar ouvindo apenas o que passa em Gotham e quis saber tudo que o site oferece, então ele assinou para ouvir tudo que vem do site, com isso ele usou o psubscribe *.
127.0.0.1:6379> psubscribe *
Reading messages… (press Ctrl-C to quit)
1) “psubscribe”
2) “*”
3) (integer) 1
Publicando mensagens
O PUBLISH não faz ideia de quem vai receber o que ele envia, ele apenas, envia. E com essa ideia, vamos enviar para os canais que conhecemos. Que são: musica, tecnologia e gothamCity.
127.0.0.1:6379> publish musica “stompin’ at the savoy – Jim Hall”
(integer) 2
127.0.0.1:6379>
O resultado foi “(integer) 2”, o redis-cli nos informa que 2 assinantes receberam essa mensagem.
Quem assinou o canal de “musica” – no caso, eu.
E quem usou o psubscribe para ouvir tudo – no caso, o coringa.
Publicando para o canal de tecnologia.
127.0.0.1:6379> publish tecnologia “Hub de eventos com Redis”
(integer) 2
127.0.0.1:6379>
Novamente 2 assinantes recebem a mensagem, tecnologia.
E o canal que escuta tudo.
Publicando para o canal de GothamCity.
127.0.0.1:6379> publish gothamCity “Gotham esta em paz”
(integer) 2
127.0.0.1:6379>
O canal de Gotham recebe a mensagem, aqui o coringa lê a mensagem por dois lugares, pelo canal específico – GothamCity.
E pelo canal que escuta tudo.
E se houver alguma publicação para um canal que ninguém assinou?
127.0.0.1:6379> publish MundiPagg “Converta mais e aumente as vendas do seu e-commerce”
(integer) 1
127.0.0.1:6379>
Apenas um canal é capaz de ouvir a mensagem.
Assim descobrimos como utilizar o recurso de PubSub do Redis, utilizando apenas a linha de comando. Abaixo segue alguns exemplos de código que automatizam nossos exemplos acima, tanto com cache, quanto com o PubSub.
Escrevendo o código
Para nosso console, vamos precisar de um client para usar no Visual Studio, vamos usar o RedisBoost (https://github.com/andrew-bn/RedisBoost).
Preparando o Visual Studio
- File > New > Project > Console Application;
- Instalar o RedisBoost pelo nuget
- (PM> Install-Package RedisBoost).
ConnectionString
<connectionStrings>
<add name=”Redis” connectionString=”data source=localhost:6379;initial catalog=0″ /> </connectionStrings> |
Código Redis com Cache
// Redis com cache private static void RedisCache(string connectionString) { using (var pool = RedisClient.CreateClientsPool()) { IRedisClient redisClient; // Chave var cadernoHoraDeAventura = "caderno:hora-de-aventura"; var cadernoTheJoker = "caderno:the-joker"; // Cria o client using (redisClient = pool.CreateClientAsync(connectionString).Result) { // Faz de forma assincrona o inserir no Redis redisClient.SetAsync(cadernoHoraDeAventura, "2000").Wait(); Console.WriteLine("Item {0} adicionado com sucesso ao carrinho!", cadernoHoraDeAventura); // Get Item var redisHoraDeAventura = redisClient.GetAsync(cadernoHoraDeAventura).Result.As<string>(); Console.WriteLine("Valor {0} do item {1}.", redisHoraDeAventura, cadernoHoraDeAventura); // Deletando a chave var resultHoraDeAventuraDelete = redisClient.DelAsync(cadernoHoraDeAventura).Result; Console.WriteLine("Chave {0} foi deletada? {1}", cadernoHoraDeAventura, Convert.ToBoolean(resultHoraDeAventuraDelete)); // Inserindo redisClient.SetAsync(cadernoTheJoker, "2200").Wait(); Console.WriteLine("Item {0} adicionado com sucesso ao carrinho!", cadernoTheJoker); // Get Item var redisTheJoker = redisClient.GetAsync(cadernoTheJoker).Result.As<string>(); Console.WriteLine("Valor {0} do item {1}.", redisTheJoker, cadernoTheJoker); // Adicionando o tempo para expirar no caderno:the-joker redisClient.ExpireAsync(cadernoTheJoker, 180); Console.WriteLine("Chave {0} com TTL de 180 segundos.", cadernoTheJoker); Console.Read(); } } }
Resultado
Código Redis com Subscribe
// Redis com PubSub private static void RedisPubSub(string connectionString, string channel) { using (var pool = RedisClient.CreateClientsPool()) { IRedisClient redisClient; // Cria o client using (redisClient = pool.CreateClientAsync(connectionString).Result) { // Usando o PSubscribe para escutar canais específicos e genéricos using (var subscriber = redisClient.PSubscribeAsync(channel).Result) { Console.WriteLine("Ouvindo o canal {0}", channel); // Obtendo a primeira mensagem do canal, utilizando o subscriber var channelMessage = subscriber.ReadMessageAsync(ChannelMessageType.Message | ChannelMessageType.PMessage).Result; // Se não tiver nenhuma mensagem, fica esperando while (channelMessage.Value.As<string>() != null) { var messageFomChannel = channelMessage.Value.As<string>(); Console.WriteLine("Mensagem: {0}", messageFomChannel); channelMessage = subscriber.ReadMessageAsync(ChannelMessageType.Message | ChannelMessageType.PMessage).Result; } } } } }
Ao iniciar o console do subscribe, devemos escrever qual canal ele vai ouvir, com isso podemos abrir quantos canais quisermos, para seguir com os mesmos exemplos acima, vamos iniciar quatro instâncias com os mesmos nomes dos canais acima.
Canal de música
Canal de tecnologia
Canal de GothamCity
Canal Genérico
Código Redis com Publisher
private static void RedisPublisher(string connectionString) { using (var pool = RedisClient.CreateClientsPool()) { IRedisClient redisClient; // Cria o client using (redisClient = pool.CreateClientAsync(connectionString).Result) { string[] channels = { "musica", "tecnologia", "gothamCity", "MundiPagg" }; string[] messages = { "stompin' at the savoy - Jim Hall", "Hub de eventos com Redis", "Gotham esta em paz", "Converta mais e aumente as vendas do seu e-commerce" }; // Publicando mensagens para os canais do array for (int i = 0; i < channels.Length; i++) { Console.WriteLine("Publicando no canal {0} a mensagem {1}", channels[i], messages[i]); redisClient.PublishAsync(channels[i], messages[i]).Wait(); } Console.WriteLine("Mensagens enviadas! :)"); Console.Read(); } } } }
Resultado da publicação
O código acima publica as mensagens nos respectivos subscribes, o resultado final é este.
Publisher
Subscribes
O Redis tem muitos recursos legais que podem e devem ser explorados, os exemplos e explicações são simples, porém, traçam um caminho para você começar a usar essa ferramenta incrível. Para outros exemplos, acessem o link no final do artigo.
E assim finalizo e espero ter explicado de forma simples, clara e objetiva como utilizar o Redis como um hub de eventos. Mostrando a ideia e como utiliza-lo como cache e o principal, como usar o subscribe dele. Qualquer dúvida, crítica ou sugestão, sinta-se à vontade para entrar em contato.
Até a próxima! 🙂
Informações do Autor
Autor
Charles Lomboni
Desenvolvedor .NET na MundiPagg
Desenvolvedor .NET e SharePoint, entusiasta por segurança, tecnologias e música. Desde 2009 vem adquirindo experiência em diversos desafios. Reconhecido por alguns prêmios como o Jaccques Franquelin Award 2013, com o sistema Techchannel, um “youtube” para ensino, feito em Sharepoint. Atualmente faz parte do time Authorizer da MundiPagg/Stone, onde se diverte todo dia programando.
Fontes do artigo:
Contatos:
- Twitter: @charleslomboni
- Skype: charleslomboni
- E-mail: charleslomboni@gmail.com / clomboni@stone.com.br
Referências:
Publicado em agosto 12, 2016, em C#, Outros e marcado como .NET, C#, cache, csharp, hub de eventos, nosql, redis. Adicione o link aos favoritos. 2 Comentários.
Muito bom! Adorei!
Valeu Juliana ;D