Fundamentos de MQTT

Mensagens Retidas no MQTT: Como Funcionam e Quando Usar

A flag retain permite que um broker MQTT entregue imediatamente a cada novo assinante o último valor conhecido de um topic. Entenda como funciona, onde brilha e onde causa bugs de dados desatualizados.

Broker armazenando o último valor de cada topic para ilustrar as mensagens retidas MQTT entregues a novos assinantes
Rode isso no seu próprio broker MQTTTenha um broker MQTT privado e gerenciado no plano Free e comece com exemplos de código prontos.
Teste grátis Exemplos de código Sem cartão de crédito

As mensagens retidas MQTT (retained messages) resolvem um problema simples, mas irritante: um client que assina um topic precisa esperar a próxima publicação para saber qualquer coisa. Com a flag retain, o broker guarda a última mensagem daquele topic e a entrega imediatamente a cada novo assinante. Neste guia você verá exatamente como as retained messages se comportam, vai testá-las no servidor MQTT público e aprenderá quando usá-las e quando evitá-las.

O Que São Mensagens Retidas no MQTT

Todo pacote PUBLISH do MQTT carrega uma flag retain de um bit. Quando um client publica com retain igual a true, o broker faz duas coisas: encaminha a mensagem aos assinantes atuais como de costume e armazena uma cópia como a retained message daquele topic exato. Cada topic guarda no máximo uma retained message, então uma nova publicação retida substitui a anterior.

Quando um client assina depois um filtro que corresponde àquele topic, o broker envia a mensagem armazenada logo após o SUBACK. O assinante vê a flag retain ativada nessa entrega, o que lhe diz "este é o último valor conhecido, não um evento novo". Assinaturas com wildcard também funcionam: assinar factory/+/status retorna de uma vez a retained message de cada topic correspondente.

Algumas regras fáceis de deixar passar:

  • A retenção é por topic, não por client. Qualquer client pode sobrescrever o valor retido.
  • Publicar com retain e um payload vazio (zero bytes) apaga a retained message.
  • Mensagens encaminhadas a assinantes já conectados normalmente chegam com a flag retain desativada no MQTT 3.1.1. O MQTT 5 adiciona a opção de assinatura "retain as published" para mantê-la.
  • O QoS da entrega retida é o menor entre o QoS da mensagem armazenada e o QoS da assinatura.

Se precisar relembrar como um broker roteia mensagens em geral, leia antes o que um broker MQTT faz.

Como a Flag Retain Muda a Entrega

A forma mais fácil de entender a diferença é comparar a mesma publicação com e sem retain.

Cenário Retain false Retain true
Assinante online no momento da publicação Recebe a mensagem Recebe a mensagem
Assinante se conecta 5 minutos depois Não recebe nada até a próxima publicação Recebe o último valor imediatamente
Segunda publicação no mesmo topic Entregue, nada é armazenado Entregue, substitui o valor armazenado
Publicar payload vazio Entrega uma mensagem vazia Apaga o valor armazenado
Assinatura com wildcard Apenas mensagens futuras Último valor de cada topic correspondente

É por isso que as retained messages costumam ser descritas como o "último valor bom conhecido". Elas transformam um fluxo de eventos em algo que você pode consultar simplesmente assinando.

Teste Mensagens Retidas em um Servidor MQTT Público

Você pode testar isso em menos de um minuto com as ferramentas de linha de comando do Mosquitto contra o servidor MQTT público em broker.connectmq.com. Ele aceita conexões anônimas com qualquer client ID não vazio. Use um prefixo de topic único, porque tudo no servidor MQTT público pode ser lido por todos, e reserve-o para testes e protótipos, nunca para dados de produção.

Primeiro publique um valor retido e desconecte:

mosquitto_pub -h broker.connectmq.com -p 1883 -i demo-pub-r7k2 \
  -t connectmq/demo/r7k2/thermostat/setpoint \
  -m '{"setpoint":21.5,"unit":"C"}' -q 1 -r

Agora assine a partir de outro terminal. Mesmo sem ninguém publicando, o valor chega instantaneamente. A flag -v imprime o topic, e -F permite mostrar a flag retain explicitamente:

mosquitto_sub -h broker.connectmq.com -p 1883 -i demo-sub-r7k2 \
  -t 'connectmq/demo/r7k2/#' -F 'retained=%r %t %p'

Você deve ver retained=1 seguido do topic e do payload. Publique de novo sem -r com o assinante aberto e a nova linha mostrará retained=0, porque é uma mensagem ao vivo e não uma armazenada.

Para apagar o valor retido, publique uma mensagem retida vazia. A flag -n envia um payload nulo:

mosquitto_pub -h broker.connectmq.com -p 1883 -i demo-pub-r7k2 \
  -t connectmq/demo/r7k2/thermostat/setpoint -r -n

Assine de novo e nada volta. Abordamos a limpeza em mais profundidade, incluindo scripts de limpeza com wildcard, em como apagar uma retained message.

Publicando Mensagens Retidas com Python

No código da aplicação, a flag retain é apenas um parâmetro. Aqui está um exemplo completo com paho-mqtt 2.x que publica um estado de dispositivo retido e depois o lê de volta com um client novo:

import json
import time
import uuid
import paho.mqtt.client as mqtt

BROKER = "broker.connectmq.com"
PREFIX = f"connectmq/demo/{uuid.uuid4().hex[:6]}"
TOPIC = f"{PREFIX}/pump-07/state"

# 1. Publica um estado retido e desconecta
pub = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id=f"pub-{uuid.uuid4().hex[:8]}")
pub.connect(BROKER, 1883, keepalive=30)
pub.loop_start()
info = pub.publish(TOPIC, json.dumps({"running": True, "rpm": 1480}), qos=1, retain=True)
info.wait_for_publish()
pub.loop_stop()
pub.disconnect()

# 2. Um novo assinante recebe o valor armazenado imediatamente
def on_connect(client, userdata, flags, reason_code, properties):
    client.subscribe(TOPIC, qos=1)

def on_message(client, userdata, msg):
    print(f"{msg.topic} retain={msg.retain} payload={msg.payload.decode()}")

sub = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id=f"sub-{uuid.uuid4().hex[:8]}")
sub.on_connect = on_connect
sub.on_message = on_message
sub.connect(BROKER, 1883, keepalive=30)
sub.loop_start()
time.sleep(3)
sub.loop_stop()
sub.disconnect()

O assinante imprime retain=True mesmo tendo se conectado depois que o publicador já tinha saído. Em um dashboard ou em um gêmeo digital, isso significa que a interface pode renderizar o estado atual ao carregar, em vez de mostrar campos vazios.

Quando Usar Mensagens Retidas no MQTT

Retained messages funcionam melhor para dados que descrevem um estado atual, e não um evento:

  1. Status do dispositivo. Flags online/offline, versão de firmware, modo de operação. Combinado com o Last Will, isso oferece uma presença confiável; veja status online de dispositivos com MQTT.
  2. Configuração e setpoints. Um dispositivo que reinicia assina seu topic de configuração e recebe seus ajustes sem uma chamada de API separada.
  3. Medições que mudam devagar. O nível de um reservatório de saneamento que é atualizado a cada 10 minutos é inútil para um dashboard recém-aberto, a menos que o último valor esteja retido.
  4. Metadados de descoberta. Muitas ferramentas residenciais e industriais publicam descritores retidos para que novos consumidores encontrem os dispositivos.
  5. Estado inicial de gêmeos digitais. Um gêmeo precisa de um panorama completo na inicialização, e topics retidos o fornecem com uma única assinatura com wildcard.

Quando Não Usar Mensagens Retidas

A flag retain não é um banco de dados nem uma fila. Evite-a para:

  • Eventos e comandos. Um comando "abrir válvula" retido será reenviado a cada dispositivo que assinar depois, inclusive após um reboot. Esse é um bug clássico e perigoso. Comandos não devem ser retidos e, de preferência, devem ter expiração; veja o message expiry interval do MQTT.
  • Histórico de telemetria de alta frequência. Apenas a última mensagem é guardada. Se você precisa de histórico, rode um assinante que grave em um banco de séries temporais.
  • Alarmes que precisam ser reconhecidos. Um alarme retido continua visível depois de resolvido, a menos que algo o sobrescreva explicitamente.

Armadilhas e Solução de Problemas

Valores desatualizados depois que um dispositivo é desativado. Retained messages vivem até que alguém as apague. Inclua a limpeza no seu procedimento de desativação e publique um payload retido vazio em cada topic que pertencia ao dispositivo.

Dados fantasmas de execuções de teste. Durante o desenvolvimento é fácil deixar lixo retido nos topics. Um prefixo único por projeto torna a limpeza com um assinante de wildcard muito mais fácil.

Reenvios inesperados ao assinar novamente. Todo SUBSCRIBE dispara a entrega retida de novo, o que pode surpreender um código que reassina ao reconectar. O MQTT 5 oferece a opção de assinatura retain handling: 0 envia retained messages a cada subscribe, 1 apenas se a assinatura for nova, 2 nunca. Verifique se a sua biblioteca client a expõe.

A flag retain aparece como false em mensagens ao vivo. Isso é esperado no MQTT 3.1.1. Se a sua lógica depende de saber se uma mensagem foi originalmente retida, use MQTT 5 com retain as published.

Valores retidos após reiniciar o broker. Se as retained messages sobrevivem a um reinício do broker depende da configuração de persistência dele. Projete os dispositivos para republicar seu estado periodicamente ou ao reconectar, de modo que um broker novo seja repovoado rapidamente, em vez de presumir que o armazenamento retido é permanente.

O comportamento está definido na especificação OASIS MQTT 5.0, caso você queira o texto normativo exato.

Mensagens Retidas em um Broker MQTT Gerenciado

Em um broker MQTT gerenciado você não configura o armazenamento retido por conta própria, mas continua sendo dono do design de topics. O ConnectMQ suporta retained messages no MQTT 3.1.1 e 5.0, e seu portal inclui um explorador de topics ao vivo e um client MQTT no navegador, para que você assine o seu prefixo e veja os valores retidos chegarem no momento em que se conecta. Isso facilita identificar dados de teste desatualizados ou um dispositivo que nunca fez a própria limpeza.

Um checklist prático antes de ir para produção:

  1. Decida por topic: estado (retain) ou evento (sem retain).
  2. Nunca retenha comandos.
  3. Republique o estado a cada reconexão, não apenas quando ele mudar.
  4. Limpe os topics retidos quando os dispositivos forem aposentados.
  5. Mantenha os payloads retidos pequenos; cada novo assinante recebe todos eles de uma vez.

Para saber mais sobre o protocolo como um todo, o tutorial de MQTT percorre publish, subscribe, QoS e sessões de ponta a ponta, e o guia de broker MQTT na nuvem explica como brokers hospedados se encaixam em uma implantação real.

Comece com o ConnectMQ

Crie um broker gratuito em app.connectmq.com no plano Serverless, sem cartão de crédito. Você recebe usuário, senha e client ID em minutos e pode ver seus topics retidos aparecerem no explorador de topics do ConnectMQ assim que o seu primeiro dispositivo publicar.

Perguntas frequentes

Quantas retained messages um topic pode ter?

Exatamente uma. Uma nova publicação retida no mesmo topic substitui a anterior, e um payload retido vazio a remove.

Retained messages expiram?

Não por padrão no MQTT 3.1.1. No MQTT 5 você pode definir um message expiry interval em uma publicação retida, depois do qual o broker deixa de entregá-la a novos assinantes.

O QoS afeta as retained messages?

A retained message mantém o QoS com que foi publicada, e um novo assinante a recebe no menor valor entre esse QoS e o QoS da sua própria assinatura.

Posso ver quais topics têm retained messages?

Assine um wildcard amplo como your/prefix/# e todas as retained messages abaixo dele serão entregues imediatamente. No ConnectMQ você pode fazer o mesmo pelo client no navegador do portal.

Artigos relacionados

Por que Seu Cliente MQTT Fica Desconectando (e Como Corrigir)

Loops de reconexão estão entre os problemas mais comuns do MQTT. Conheça as cinco causas habituais, de client IDs duplicados a timeouts de keep alive e pacotes grandes demais, e siga um fluxo de diagnóstico que identifica a sua.

9 min de leitura

Quem Inventou o MQTT? A História dos Oleodutos à IoT

O MQTT foi inventado em 1999 por Andy Stanford-Clark, da IBM, e Arlen Nipper, da Arcom, para monitorar oleodutos via satélite. Acompanhe sua trajetória até o open source, a OASIS, a ISO e os brokers MQTT gerenciados na nuvem de hoje.

8 min de leitura

Todos os artigos →

Seu broker MQTT privado está a poucos cliques de distância

Crie uma conta, receba as credenciais do seu broker e conecte seu primeiro dispositivo — sem servidores para instalar, atualizar ou escalar.