Redis PubSub com Python

paulosouzainfo

PauloSouza.info

Posted on June 23, 2022

Redis PubSub com Python

Atualmente, quando falamos de PubSub, temos inúmeras opções para discutir quando falamos de clientes e servidores.

Basicamente, temos um publicador de um lado e um ouvinte do outro aguardando um dado. De forma simplificada — caso você ainda não tenha lido sobre isso, é como o professor lá na frente explicando uma matéria e do outro lado, 40 alunos na mesma sala anotando tudo aquilo que escutam.

Bem fácil, né?

Sistemas já conhecidos de mensageiros como RabbitMQ, ZeroMQ, Kafka e Nats.io promovem para cada solução, uma forma de implantar isso no seu código onde a distribuição dos dados mesmo que em ambientes diferentes, possa ser propagado com segurança.

No navegador, para uma comunicação através de um Websocket ou EventSource, também temos um publicador e múltiplos ouvintes como em uma sala de bate-papo, mas de formas distintas. O Websocket é um sistema de 2 vias onde ele pode ser o publicador e ouvinte, enquanto no EventSource uma única via é utilizada na comunicação do servidor com os clientes.

O Redis, conhecido pela sua velocidade, já possui nativamente a funcionalidade para PubSub sem a necessidade de configurações adicionais, mas com suas limitações onde nas ferramentas citadas teremos soluções mais robustas, com persistência de dados, streaming e por aí vai... Mas estamos aqui para falar do Redis PubSub.

Botando o Redis pra funcionar

Para testes, você pode subir um container na sua máquina mesmo para o Redis utilizando o Docker.

docker run -ti --rm -p 6379:6379 --name pubsub redis:alpine
Enter fullscreen mode Exit fullscreen mode

Como Redis ativo, abra uma nova aba/janela da sua linha de comando para testarmos o canal pythonpubsub como ouvinte.

docker exec -ti pubsub redis-cli subscribe pythonpubsub
Enter fullscreen mode Exit fullscreen mode

Para testarmos a publicação no mesmo canal, abra uma nova aba/janela na sua linha de comando e vamos ver a máquina acontecer.

docker exec -ti pubsub redis-cli publish pythonpubsub "eu sou uma mensagem"
Enter fullscreen mode Exit fullscreen mode

Divertido, né?... Mas aí você se pergunta sobre a velocidade e nesta aba/janela que você publicou a mensagem, vamos fazer um for simples para publicar 10000 mensagens.

for i in {1..10000}; do
    docker exec -ti pubsub redis-cli publish pythonpubsub "mensagem $i";
done
Enter fullscreen mode Exit fullscreen mode

Agora que configuramos o ambiente como container Redis e testamos o PubSub, feche todas as janelas mantendo apenas a aba/janela da sua linha de comando onde o servidor Redis está rodando. Tá na hora de escrever um código bem simples em Python. Tão simples que é bem próximo do que fizemos até agora e isso vai ampliar seus horizontes.

Partindo para o código em Python

Mas... Python? Só Python? Não! O exemplo é em Python - por uma paixão pessoal e ser melhor na leitura do código, mas pode ser também com o uso de bibliotecas equivalentes para NodeJS, PHP, Golang, Java ou qualquer outra linguagem da sua preferência.

Aqui, na minha máquina local, eu estou usando o Python na versão 3.9.13, mas em testes recentes eu não tive problema de compatibilidade em versões 3.6+.

No caso do Python, é sempre importante ter o ambiente virtual ativo para que assim possamos isolar as dependências entre projetos.

python3 -m venv venv
Enter fullscreen mode Exit fullscreen mode

Inicie o ambiente virtual para iniciar a instalação da única dependência que teremos com a biblioteca de conexão para o Redis.

. venv/bin/activate
Enter fullscreen mode Exit fullscreen mode

Instale a biblioteca redis.

pip3 install redis
Enter fullscreen mode Exit fullscreen mode

Crie um arquivo chamado app.py e nele, vamos inserir o nosso código de subscriber como um daemon que se manterá ativo até o encerramento do programa (o famoso ctrl+c).

from redis import StrictRedis

client = StrictRedis(host="localhost", port=6379)

pubsub = client.pubsub()
pubsub.subscribe('pythonpubsub')

while True:
    msg = pubsub.get_message()

    if msg:
        if not isinstance(msg['data'], int):
            channel, message = msg['channel'], msg['data']
            print('%s: %s' % (channel.decode('utf-8'), message.decode('utf-8')))
Enter fullscreen mode Exit fullscreen mode

Rode o arquivo app.py.

python3 app.py
Enter fullscreen mode Exit fullscreen mode

Junto com a aplicação já rodando, abra outra aba/janela na sua linha de comando e deixe o subscriber do Redis rodando do lado.

docker exec -ti pubsub redis-cli subscribe pythonpubsub
Enter fullscreen mode Exit fullscreen mode

Sabe aquele for que criamos lá em cima? Abra uma nova aba/janela da sua linha de comando e vamos ver as mensagens sendo propagadas em ambas as janelas.

for i in {1..10000}; do
    docker exec -ti pubsub redis-cli publish pythonpubsub "mensagem $i";
done
Enter fullscreen mode Exit fullscreen mode

Bem legal, né? Vou te falar que isso já me salvou algumas vezes para aumentar a velocidade de processamento paralelo em algumas aplicações sem grandes mudanças ou necessidade de refactoring.

Espero que você tenha curtido. Sigo aberto a sugestões e boas idéias.

💖 💪 🙅 🚩
paulosouzainfo
PauloSouza.info

Posted on June 23, 2022

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related