Redis PubSub com Python
Tags: python, pubsub, redis
Published: 2022-06-23 14:36:18

---
title: Redis PubSub com Python
published: true
description: É fácil manter comunicações ativas e em tempo real através do conceito de Publishers e Subscribers.
tags: python, pubsub, redis
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wc6pg4t1af6z1ewja6rr.png
---

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](https://redis.io/), 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](https://redis.io/commands/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
```

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
```

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"
``` 

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
```

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
```

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
```

Instale a biblioteca redis.

```
pip3 install redis
```

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')))
```

Rode o arquivo app.py.

```
python3 app.py
```

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
```

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
```

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.