DEV Community

Cover image for Redis PubSub com Python
PauloSouza.info
PauloSouza.info

Posted on

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.

Top comments (0)