Protocolo de armazenamento de estado para Agente MQTT
Importante
A Versão Prévia das Operações da Internet das Coisas do Azure – habilitadas pelo Azure Arc – está atualmente em versão prévia. Você não deve usar esse software em versão prévia em ambientes de produção.
Você precisará implantar uma nova instalação das Operações da Internet das Coisas do Azure quando uma versão em disponibilidade geral for disponibilizada. Você não poderá atualizar uma instalação de versão prévia.
Veja os Termos de Uso Complementares para Versões Prévias do Microsoft Azure para obter termos legais que se aplicam aos recursos do Azure que estão em versão beta, versão prévia ou que, de outra forma, ainda não foram lançados em disponibilidade geral.
O armazenamento de estado do MQ é um sistema de armazenamento distribuído dentro do cluster de Operações do Azure IoT. O armazenamento de estado oferece as mesmas garantias de alta disponibilidade que as mensagens MQTT no Agente MQTT. De acordo com as diretrizes de protocolo MQTT5/RPC, os clientes devem usar o MQTT5 para interagir com o armazenamento de estado do MQ. Este artigo fornece diretrizes de protocolo para desenvolvedores que precisam implementar seus próprios clientes de armazenamento de estado para Agente MQTT.
Visão geral do protocolo de armazenamento de estado
O armazenamento de estado do MQ dá suporte aos seguintes comandos:
SET
<keyName><keyValue><setOptions>GET
<keyName>DEL
<keyName>VDEL
<keyName><keyValue> ## Exclui um determinado <keyName> se e somente se seu valor for <keyValue>
O protocolo usa o seguinte modelo de solicitação-resposta:
- Solicitação. Os clientes publicam uma solicitação em um tópico do sistema de armazenamento de estado bem definido. Para publicar a solicitação, os clientes usam as propriedades e a carga necessárias descritas nas seções a seguir.
- Resposta. O armazenamento de estado processa de maneira assíncrona a solicitação e responde no tópico de resposta que o cliente forneceu inicialmente.
O diagrama a seguir mostra a exibição básica da solicitação e da resposta:
Tópico do sistema de armazenamento de estado, QoS e propriedades MQTT5 necessárias
Para se comunicar com o armazenamento de estado, os clientes devem atender aos seguintes requisitos:
- Use MQTT5. Para obter mais informações, consulte as especificações do MQTT 5.
- Use QoS 1 (Qualidade de Serviço de nível 1). O QoS 1 está descrito na especificação MQTT 5.
- Tenha um relógio que esteja dentro de um minuto do relógio do Agente MQTT.
Para se comunicar com o armazenamento de estado, os clientes devem PUBLISH
solicitações para o tópico do sistema statestore/v1/FA9AE35F-2F64-47CD-9BFF-08E2B32A0FE8/command/invoke
. Como o armazenamento de estado faz parte das Operações do Azure IoT, ele faz uma SUBSCRIBE
implícita a este tópico sobre a inicialização.
Para criar uma solicitação, as seguintes propriedades MQTT5 são necessárias. Se essas propriedades não estiverem presentes ou a solicitação não for do tipo QoS 1, a solicitação falhará.
- Tópico de Resposta. O armazenamento de estado responde à solicitação inicial usando esse valor. Como prática recomendada, formate o tópico de resposta como
clients/{clientId}/services/statestore/_any_/command/invoke/response
. Definir o tópico de resposta comostatestore/v1/FA9AE35F-2F64-47CD-9BFF-08E2B32A0FE8/command/invoke
ou como um que começa comclients/statestore/v1/FA9AE35F-2F64-47CD-9BFF-08E2B32A0FE8
não é permitido em uma solicitação de repositório de estado. O repositório de estado desconecta clientes MQTT que usam um tópico de resposta inválido. - Dados de Correlação. Quando o armazenamento de estado envia uma resposta, ele inclui os dados de correlação da solicitação inicial.
O diagrama a seguir mostra uma exibição expandida da solicitação e da resposta:
Comandos com suporte:
Os comandos SET
, GET
e DEL
se comportam conforme o esperado.
Os valores que o comando SET
define e o comando GET
recupera são dados binários arbitrários. O tamanho dos valores é limitado apenas pelo tamanho máximo do conteúdo MQTT e limitações de recursos do MQ e do cliente.
SET
options
O comando SET
fornece mais sinalizadores opcionais além dos básicos keyValue
e keyName
:
NX
. Permite que a chave seja definida somente se ela ainda não existir.NEX <value>
. Permite que a chave seja definida somente se a chave não existir ou se o valor da chave já estiver definido como <valor>. O sinalizadorNEX
normalmente é usado para um cliente renovar a expiração (PX
) em uma chave.PX
. Por quanto tempo a chave deve persistir antes de expirar, em milissegundos.
VDEL
options
O comando VDEL
é um caso especial do comando DEL
. DEL
exclui incondicionalmente o keyName
determinado. VDEL
requer outro argumento chamado keyValue
. VDEL
só excluirá o keyName
determinado se tiver o mesmo keyValue
.
Formato de conteúdo
O formato de conteúdo PUBLISH
do armazenamento de estado é inspirado em RESP3, que é o protocolo subjacente que o Redis usa. O RESP3 codifica o verbo, como SET
ou GET
, e os parâmetros, como keyName
e keyValue
.
Diferenciar maiúsculas de minúsculas
O cliente deve enviar os verbos e as opções em maiúsculas.
Formato de solicitação
As solicitações são formatadas como no exemplo a seguir. Após RESP3, o *
representa o número de itens em uma matriz. O caractere $
é o número de caracteres na linha a seguir, excluindo o CRLF à direita.
Os comandos com suporte no formato RESP3 são GET
, SET
, DEL
e VDEL
.
*{NUMBER-OF-ARGUMENTS}<CR><LF>
${LENGTH-OF-NEXT-LINE}<CR><LF>
{COMMAND-NAME}<CR><LF>
${LENGTH-OF-NEXT-LINE}<CR><LF> // This is always the keyName with the current supported verbs.
{KEY-NAME}<CR><LF>
// Next lines included only if command has additional arguments
${LENGTH-OF-NEXT-LINE}<CR><LF> // This is always the keyValue for set
{KEY-VALUE}<CR><LF>
A saída de exemplo a seguir mostra o conteúdo RESP3 do armazenamento de estado:
*3<CR><LF>$3<CR><LF>set<CR><LF>$7<CR><LF>SETKEY2<CR><LF>$6<CR><LF>VALUE5<CR><LF>
*2<CR><LF>$3<CR><LF>get<CR><LF>$7<CR><LF>SETKEY2<CR><LF>
*2<CR><LF>$3<CR><LF>del<CR><LF>$7<CR><LF>SETKEY2<CR><LF>
*3<CR><LF>$4<CR><LF>vdel<CR><LF>$7<CR><LF>SETKEY2<CR><LF>$3<CR><LF>ABC<CR><LF>
Observação
Observe que SET
requer propriedades MQTT5 adicionais, conforme explicado na seção Controle de versão e relógios lógicos híbridos.
Formato de resposta
Quando o armazenamento de estado detecta um conteúdo RESP3 inválido, ele ainda retorna uma resposta ao Response Topic
do solicitante. Exemplos de conteúdo inválido incluem um comando inválido, um RESP3 ilegal ou um estouro inteiro. Um conteúdo inválido começa com a cadeia de caracteres -ERR
e contém mais detalhes.
Observação
Uma solicitação GET
, DEL
ou VDEL
em uma chave inexistente não é considerada um erro.
Se um cliente enviar um conteúdo inválido, o armazenamento de estado enviará uma carga semelhante ao seguinte exemplo:
-ERR syntax error
Resposta SET
Quando uma solicitação de SET
for bem-sucedida, o armazenamento de estado retornará o seguinte conteúdo:
+OK<CR><LF>
Se uma solicitação SET falhar devido a uma verificação de condição especificada nas opções de conjunto NX ou NEX que significa que a chave não pode ser definida, o armazenamento de estado retornará a seguinte carga útil:
-1<CR><LF>
Resposta GET
Quando uma solicitação de GET
é feita em uma chave inexistente, o armazenamento de estado retorna o seguinte conteúdo:
$-1<CR><LF>
Quando a chave é encontrada, o armazenamento de estado retorna o valor no seguinte formato:
${NumberOfBytes}<CR><LF>
{KEY-VALUE}
A saída do armazenamento de estado que retorna o valor 1234
se parece com o seguinte exemplo:
$4<CR><LF>1234<CR><LF>
Resposta DEL
e VDEL
O armazenamento de estado retorna o número de valores excluídos em uma solicitação de exclusão. Atualmente, o armazenamento de estado só pode excluir um valor por vez.
:{NumberOfDeletes}<CR><LF> // Will be 1 on successful delete or 0 if the keyName is not present
A saída a seguir é um exemplo de um comando DEL
bem-sucedido:
:1<CR><LF>
Se uma solicitação VDEL falhar porque o valor especificado não corresponde ao valor associado à chave, o armazenamento de estado retornará a seguinte carga útil:
-1<CR><LF>
-ERR
respostas
A seguir está a lista atual de sequências de erros. Seu aplicativo cliente deve manipular cadeias de caracteres de erro desconhecido para dar suporte a atualizações no armazenamento de estado.
Cadeia de caracteres de erro retornada do armazenamento de estado | Explicação |
---|---|
o registro de data e hora solicitado está muito distante no futuro; certifique-se de que os relógios do sistema do cliente e do corretor estejam sincronizados | Carimbo de data/hora solicitado inesperado causado pelo armazenamento de estado e os relógios do cliente não estão sincronizados. |
um token de esgrima é necessário para essa solicitação | Ocorre um erro se uma chave estiver marcada com um token de cerca, mas o cliente não especificar o token de cerca. |
o carimbo de data/hora do token de esgrima solicitado está muito distante no futuro; certifique-se de que os relógios do sistema do cliente e do corretor estejam sincronizados | Carimbo de data/hora inesperado do token de cerca causado pela falta de sincronização dos relógios do cliente e do armazenamento de estado. |
o token de cerca solicitado é uma versão inferior ao token de cerca que protege o recurso | Versão incorreta do token de esgrima solicitado. Para obter mais informações, veja [Versionamento e relógios lógicos híbridos].(#versioning-and-hybrid-logical-clocks) |
a cota foi excedida | O armazenamento de estado tem uma cota de quantas chaves ele pode armazenar, que é baseada no perfil de memória do broker MQTT especificado. |
erro de sintaxe | A carga enviada não está de acordo com a definição do armazenamento de estado. |
não autorizado | Erro de autorização |
comando desconhecido | O comando não é reconhecido. |
número errado de argumentos | Número incorreto de argumentos esperados. |
carimbo de data/hora ausente | Quando os clientes fazem um SET, eles devem definir a propriedade de usuário MQTT5 __ts como um HLC representando seu registro de data e hora. |
carimbo de data/hora malformado | O registro de data e hora no __ts ou no token de esgrima não é legal. |
o comprimento da chave é zero | As chaves não podem ter comprimento zero no armazenamento de estado. |
Controle de versão e relógios lógicos híbridos
Esta seção descreve como o armazenamento de estado lida com o controle de versão.
Versões como relógios lógicos híbridos
O armazenamento de estado mantém uma versão para cada valor armazenado. O armazenamento de estado poderia usar um contador de aumento de forma monotônica para manter versões. Em vez disso, o armazenamento de estado usa um HLC (Relógio Lógico Híbrido) para representar versões. Para obter mais informações, consulte os artigos sobre o design original de HLCs e a intenção por trás de HLCs.
O armazenamento de estado usa o seguinte formato para definir HLCs:
{wallClock}:{counter}:{node-Id}
O wallClock
é o número de milissegundos desde a época do Unix. counter
e node-Id
funcionam como HLCs em geral.
Quando os clientes fazem um SET
, eles devem definir a propriedade de usuário MQTT5 __ts
como um HLC, representando seu carimbo de data/hora, com base no relógio atual do cliente. O armazenamento de estado retorna a versão do valor em sua mensagem de resposta. A resposta também é especificada como um HLC e também usa a propriedade de usuário MQTT5 __ts
. O HLC retornado é sempre maior que o HLC da solicitação inicial.
Exemplo de configuração e recuperação da versão de um valor
Esta seção mostra um exemplo de configuração e obtenção da versão para um valor.
Um cliente define keyName=value
. O relógio do cliente é 3 de outubro, 23:07:05 GMT. O valor do relógio é 1696374425000
milissegundos desde a época do Unix. Suponha que o relógio do sistema do armazenamento de estado seja idêntico ao relógio do sistema cliente. O cliente faz o comando SET
conforme descrito anteriormente.
O diagrama a seguir ilustra o comando SET
:
A propriedade __ts
(carimbo de data/hora) no conjunto inicial contém 1696374425000
como o relógio de parede do cliente, o contador como 0
e sua ID de nó como CLIENT
. Na resposta, a propriedade __ts
retornada pelo armazenamento de estado contém o wallClock
, o contador incrementado por um e a ID do nó como StateStore
. O repositório de estado poderia retornar um valor de wallClock
mais alto se o relógio estivesse adiantado, com base na maneira como as atualizações do HLC funcionam.
Essa versão também é retornada em solicitações de GET
, DEL
e VDEL
bem-sucedidas. Nessas solicitações, o cliente não especifica um __ts
.
O diagrama a seguir ilustra o comando GET
:
Observação
O carimbo de data/hora __ts
que o armazenamento de estado retorna é o mesmo que retornou na solicitação de SET
inicial.
Se uma determinada chave for atualizada posteriormente com um novo SET
, o processo será semelhante. O cliente deve definir sua solicitação __ts
com base no relógio atual. O armazenamento de estado atualiza a versão do valor e retorna o __ts
seguindo as regras de atualização do HLC.
Distorção de relógio
O armazenamento de estado rejeita um __ts
(e também um __ft
) que está mais de um minuto à frente do relógio local do armazenamento de estado.
O armazenamento de estado aceita um __ts
que está atrás do relógio local do armazenamento de estado. Conforme especificado no algoritmo HLC, o armazenamento de estado define a versão da chave como seu relógio local porque ela é maior.
Tokens de bloqueio e isolamento
Esta seção descreve a finalidade e o uso de tokens de bloqueio e isolamento.
Tela de fundo
Suponha que haja dois ou mais clientes MQTT usando o armazenamento de estado. Ambos os clientes querem gravar em uma determinada chave. Os clientes do armazenamento de estado precisam de um mecanismo para bloquear a chave de forma que apenas um cliente por vez possa modificar uma determinada chave.
Um exemplo desse cenário ocorre em sistemas ativos e em espera. Pode haver dois clientes que executam a mesma operação e a operação pode incluir o mesmo conjunto de chaves do armazenamento de estado. Em um determinado momento, um dos clientes está ativo e o outro está pronto para assumir imediatamente se o sistema ativo trava ou falha. Idealmente, apenas um cliente deve gravar no armazenamento de estado em um determinado momento. No entanto, em sistemas distribuídos, é possível que ambos os clientes se comportem como se estivessem ativos e, simultaneamente, tentem gravar nas mesmas chaves. Esse cenário cria uma condição de corrida.
O armazenamento de estado fornece mecanismos para impedir essa condição de corrida usando tokens de isolamento. Para obter mais informações sobre tokens de isolamento e a classe de condições de corrida contra as quais eles foram projetados para se proteger, consulte este artigo.
Obter um token de isolamento
Este exemplo pressupõe que temos os seguintes elementos:
Client1
eClient2
. Esses clientes são clientes de armazenamento de estado que atuam como um par ativo e em espera.LockName
. O nome de uma chave no armazenamento de estado que atua como o bloqueio.ProtectedKey
. A chave que precisa ser protegida contra vários gravadores.
Os clientes tentam obter um bloqueio como a primeira etapa. Eles recebem um bloqueio fazendo um SET LockName {CLIENT-NAME} NEX PX {TIMEOUT-IN-MILLISECONDS}
. Lembre-se de Definir Opções que o sinalizador NEX
significa que o SET
só terá êxito se uma das seguintes condições for atendida:
- A chave estava vazia
- O valor da chave já está definido como <valor> e
PX
especifica o tempo limite em milissegundos.
Suponha que Client1
vá primeiro com uma solicitação de SET LockName Client1 NEX PX 10000
. Essa solicitação lhe dá a propriedade de LockName
para 10.000 milissegundos. Se Client2
tentar um SET LockName Client2 NEX ...
enquanto Client1
tiver o bloqueio, o sinalizador NEX
significará que a solicitação Client2
falhará. Client1
precisa renovar esse bloqueio enviando o mesmo comando SET
usado para adquirir o bloqueio, se Client1
quiser continuar a propriedade.
Observação
Um SET NX
é conceitualmente equivalente a AcquireLock()
.
Usar os tokens de isolamento em solicitações SET
Quando Client1
faz SET
com êxito ("AquireLock") no LockName
, o armazenamento de estado retorna a versão de LockName
como um HLC (Relógio Lógico Híbrido) na propriedade __ts
do usuário MQTT5.
Quando um cliente executa uma solicitação de SET
, ele pode incluir opcionalmente a propriedade de usuário MQTT5 __ft
para representar um "token de isolamento". O __ft
é representado como um HLC. O token de isolamento associado a um determinado par chave-valor fornece verificação de propriedade de bloqueio. O token de isolamento pode vir de qualquer lugar. Para esse cenário, ele deve vir da versão do LockName
.
O diagrama a seguir mostra o processo de Client1
fazer uma solicitação SET
no LockName
:
Em seguida, Client1
usa a propriedade __ts
(Property=1696374425000:1:StateStore
) não modificada como base da propriedade __ft
na solicitação para modificar ProtectedKey
. Como todas as solicitações SET
, o cliente deve definir a propriedade __ts
de ProtectedKey
.
O diagrama a seguir mostra o processo de Client1
fazer uma solicitação SET
no ProtectedKey
:
Se a solicitação for bem-sucedida, desse ponto em ProtectedKey
exigirá um token de isolamento igual ou maior que o especificado na solicitação SET
.
Algoritmo de token de isolamento
O armazenamento de estado aceita qualquer HLC para o __ts
de um par chave-valor, se o valor estiver dentro da distorção máxima do relógio. No entanto, o mesmo não ocorre em tokens de isolamento.
O algoritmo do armazenamento de estado para tokens de isolamento é o seguinte:
- Se um par chave-valor não tiver um token de isolamento associado a ele e uma solicitação
SET
define__ft
, o armazenamento de estado armazenará o__ft
associado com o par chave-valor. - Se um par chave-valor tiver um token de isolamento associado a ele:
- Se uma solicitação
SET
não tiver especificado__ft
, rejeite a solicitação. - Se uma solicitação
SET
especificar um__ft
que tenha um valor HLC mais antigo do que o token de isolamento associado ao par chave-valor, rejeite a solicitação. - Se uma solicitação
SET
especificar um__ft
que tenha um valor HLC igual ou mais recente do que o token de isolamento associado ao par chave-valor, aceite a solicitação. O armazenamento de estado atualiza o token de isolamento do par chave-valor para ser o único definido na solicitação, se ele for mais recente.
- Se uma solicitação
Depois que uma chave é marcada com um token de isolamento, para que uma solicitação seja bem-sucedida, as solicitações DEL
e VDEL
também exigem que a propriedade __ft
seja incluída. O algoritmo é idêntico ao anterior, exceto que o token de isolamento não é armazenado porque a chave está sendo excluída.
Comportamento do cliente
Esses mecanismos de bloqueio dependem de clientes serem bem comportados. No exemplo anterior, um Client2
mal comportado não podia ter o LockName
e ainda executar com êxito um SET ProtectedKey
escolhendo um token de isolamento mais recente que o token de ProtectedKey
. O armazenamento de estado não está ciente de que LockName
e ProtectedKey
têm qualquer relação. Como resultado, o armazenamento de estado não executa a validação de que Client2
realmente possui o valor.
Os clientes que podem gravar chaves para as quais eles realmente não possuem o bloqueio são comportamentos indesejáveis. Você pode proteger contra esse mau comportamento do cliente implementando corretamente os clientes e usando a autenticação para limitar o acesso a chaves somente para clientes confiáveis.
Notificações
Os clientes podem se registrar no repositório de estado para receber notificações de chaves que estão sendo modificadas. Considere o cenário em que um termostato usa a chave do repositório de estado {thermostatName}\setPoint
. Outros clientes do repositório de estado podem alterar o valor dessa chave para alterar o setPoint do termostato. Em vez de sondar alterações, o termostato pode se registrar no repositório de estado para receber mensagens quando {thermostatName}\setPoint
é modificado.
Mensagens de solicitação KEYNOTIFY
Os clientes do repositório de estado solicitam que o repositório de estado monitore uma determinada keyName
para alterações enviando uma mensagem de KEYNOTIFY
. Assim como todas as solicitações do repositório de estado, os clientes PUBLISH uma mensagem QoS1 com essa mensagem por meio do MQTT5 para o tópico do sistema do repositório de estado statestore/v1/FA9AE35F-2F64-47CD-9BFF-08E2B32A0FE8/command/invoke
.
O conteúdo da solicitação tem a forma a seguir:
KEYNOTIFY<CR><LF>
{keyName}<CR><LF>
{optionalFields}<CR><LF>
Onde:
- KEYNOTIFY é um literal de cadeia de caracteres que especifica o comando.
{keyName}
é o nome da chave para escutar as notificações. No momento, não há suporte para caracteres curinga.{optionalFields}
Os valores de campo opcionais com suporte no momento são:{STOP}
Se houver uma notificação existente com o mesmokeyName
eclientId
que essa solicitação, o repositório de estado a removerá.
A saída de exemplo a seguir mostra uma solicitação KEYNOTIFY
para monitorar a chave SOMEKEY
:
*2<CR><LF>
$9<CR><LF>
KEYNOTIFY<CR><LF>
$7<CR><LF>
SOMEKEY<CR><LF>
Mensagem de resposta KEYNOTIFY
Como todas as solicitações RPC do repositório de estado, o repositório de estado retorna sua resposta ao Response Topic
e usa as propriedades de Correlation Data
especificadas da solicitação inicial. Para KEYNOTIFY
, uma resposta bem-sucedida indica que o repositório de estado processou a solicitação. Depois que o repositório de estado processa a solicitação com êxito, ela monitora a chave do cliente atual ou interrompe o monitoramento.
Com êxito, a resposta do repositório de estado é a mesma de um SET
bem-sucedido.
+OK<CR><LF>
Se um cliente enviar uma solicitação KEYNOTIFY SOMEKEY STOP
mas o repositório de estado não estiver monitorando essa chave, a resposta do repositório de estado será a mesma que tentar excluir uma chave que não existe.
:0<CR><LF>
Qualquer outra falha segue o padrão geral de relatório de erros do repositório de estado:
-ERR: <DESCRIPTION OF ERROR><CR><LF>
Tópicos de notificação KEYNOTIFY e ciclo de vida
Quando uma keyName
sendo monitorada por meio de KEYNOTIFY
é modificada ou excluída, o repositório de estado envia uma notificação ao cliente. O tópico é determinado por convenção – o cliente não especifica o tópico durante o processo de KEYNOTIFY
.
O tópico é definido no exemplo a seguir. O clientId
é uma representação codificada em hexadecimal de maiúsculas e minúsculas da ClientId MQTT do cliente que iniciou a solicitação KEYNOTIFY
e keyName
é uma representação codificada em hexadecimal da chave que foi alterada.
clients/statestore/v1/FA9AE35F-2F64-47CD-9BFF-08E2B32A0FE8/{clientId}/command/notify/{keyName}
Por exemplo, o MQ publica uma mensagem NOTIFY
enviada para client-id1
com o nome da chave modificado SOMEKEY
para o tópico:
clients/statestore/v1/FA9AE35F-2F64-47CD-9BFF-08E2B32A0FE8/636C69656E742D696431/command/notify/534F4D454B4559`
Um cliente que usa notificações deve SUBSCRIBE
para este tópico e aguardar o SUBACK
ser recebido antes de enviar solicitações KEYNOTIFY
para que nenhuma mensagem seja perdida.
Se um cliente se desconectar, ele deverá assinar novamente o tópico de notificação KEYNOTIFY
e reenviar o comando KEYNOTIFY
para todas as chaves necessárias para continuar o monitoramento. Ao contrário das assinaturas MQTT, que podem ser mantidas em uma sessão não limpa, o repositório de estado remove internamente qualquer mensagens KEYNOTIFY
quando um determinado cliente se desconecta.
Formato de mensagem de notificação KEYNOTIFY
Quando uma chave que está sendo monitorada por meio de KEYNOTIFY
for modificada, o repositório de estado PUBLISH
uma mensagem para o tópico de notificação seguindo o formato para os clientes do repositório de estado registrados para a alteração.
NOTIFY<CR><LF>
{operation}<CR><LF>
{optionalFields}<CR><LF>
Os seguintes detalhes estão incluídos na mensagem:
NOTIFY
é um literal de cadeia de caracteres incluído como o primeiro argumento no conteúdo, indicando que uma notificação chegou.{operation}
é o evento que ocorreu. Atualmente, essas operações são:SET
o valor foi modificado. Essa operação só pode ocorrer como resultado de um comandoSET
de um cliente do repositório de estado.DEL
o valor foi excluído. Essa operação pode ocorrer devido a um comandoDEL
ouVDEL
de um cliente do repositório de estado.
optionalFields
VALUE
e{MODIFIED-VALUE}
.VALUE
é um literal de cadeia de caracteres que indica que o próximo campo,{MODIFIED-VALUE}
, contém o valor para o qual a chave foi alterada. Esse valor é enviado somente em resposta a chaves que estão sendo modificadas devido a umSET
.
A saída de exemplo a seguir mostra uma mensagem de notificação enviada quando a chave SOMEKEY
é modificada para o valor abc
, com o VALUE
incluído porque a solicitação inicial especificou a opção GET
:
*4<CR><LF>
$6<CR><LF>
NOTIFY<CR><LF>
$3<CR><LF>
SET<CR><LF>
$5<CR><LF>
VALUE<CR><LF>
$3<CR><LF>
abc<CR><LF>