Partager via


Protocole de stockage d’état

Le stockage d’état est un système de stockage distribué au sein du cluster Opérations Azure IoT. Le magasin d’états offre les mêmes garanties de haute disponibilité que les messages MQTT dans l’agent MQTT. Conformément aux lignes directrices du protocole MQTT5/RPC, les clients doivent utiliser MQTT5 pour interagir avec le stockage d’état. Cet article fournit des conseils sur le protocole aux développeurs qui ont besoin d’implémenter leurs propres clients de stockage d’état.

Vue d’ensemble

Le stockage d’état prend en charge les commandes suivantes :

  • SET<keyName><keyValue><setOptions>
  • GET<keyName>
  • DEL<keyName>
  • VDEL<keyName><keyValue> ## Supprime un nom de <keyName> si et uniquement si sa valeur est <keyValue>

Le protocole utilise le modèle requête-réponse suivant :

  • Requête. Les clients publient une requête auprès d'une rubrique bien définie du système de stockage d'informations. Pour publier la requête, les clients utilisent les propriétés requises et les données utiles décrites dans les sections suivantes.
  • Response. Le magasin d'état traite la requête de manière asynchrone et répond sur le thème de réponse initialement fourni par le client.

Le diagramme suivant montre la vue de base de la requête et de la réponse :

Diagramme du processus de demande et de réponse de base du magasin d’états.

Sujet du système de stockage d'état, QoS et propriétés MQTT5 requises

Pour communiquer avec le magasin d'État, les clients doivent remplir les conditions suivantes :

  • Utilisez MQTT5. Pour en savoir plus, consultez la spécification MQTT 5.
  • Utilisez QoS 1 (qualité de niveau de service 1). QoS 1 est décrit dans la spécification MQTT 5.
  • Avoir une horloge qui est à moins d'une minute de l'horloge du courtier MQTT.

Pour communiquer avec le magasin d’états, les clients doivent demander PUBLISH à la rubrique système statestore/v1/FA9AE35F-2F64-47CD-9BFF-08E2B32A0FE8/command/invoke. Étant donné que le magasin d’états fait partie d'Azure IoT Operations, il effectue un SUBSCRIBE implicite à cette rubrique au démarrage.

Pour construire une requête, les propriétés MQTT5 suivantes sont nécessaires. Si ces propriétés ne sont pas présentes ou si la requête n'est pas de type QoS 1, la requête échoue.

  • Rubrique de réponse. Le magasin d'état répond à la requête initiale en utilisant cette valeur. En guise de meilleure pratique, mettez en forme la rubrique de réponse en tant que clients/{clientId}/services/statestore/_any_/command/invoke/response. La définition de la rubrique de réponse comme statestore/v1/FA9AE35F-2F64-47CD-9BFF-08E2B32A0FE8/command/invoke ou qui commence par clients/statestore/v1/FA9AE35F-2F64-47CD-9BFF-08E2B32A0FE8 n’est pas autorisée sur une demande de magasin d’états. Le magasin d’états déconnecte les clients MQTT qui utilisent une rubrique de réponse non valide.
  • Données de corrélation. Lorsque le magasin d'état envoie une réponse, il inclut les données de corrélation de la requête initiale.

Le diagramme suivant montre une vue développée de la requête et de la réponse :

Diagramme du processus de demande et de réponse développé du magasin d’états.

Commandes prises en charge

Les commandes SET, GET et DEL se comportent comme prévu.

Les valeurs que la commande SET définit et que la commande GET récupère sont des données binaires arbitraires. La taille des valeurs n’est limitée que par la taille maximale de la charge utile MQTT et par les limitations de ressources de l’Agent MQTT et du client.

SET options

La commande SET fournit des indicateurs facultatifs au-delà des indicateurs de base keyValue et keyName :

  • NX. Permet de définir la clé uniquement si elle n'existe pas déjà.
  • NEX <value>. Autorise la définition de la clé uniquement si la clé n’existe pas ou si la valeur de la clé est déjà définie sur la <valeur>. L’indicateur NEX est généralement utilisé pour un client renouvelant l’expiration (PX) sur une clé.
  • PX. Durée pendant laquelle la clé doit persister avant d'expirer, en millisecondes.

VDEL options

La commande VDEL est un cas spécial de la commande DEL. DEL supprime inconditionnellement le keyName donné. VDEL nécessite un autre argument appelé keyValue. VDEL supprime uniquement le keyName donné s’il a le même keyValue.

Format de charge utile

Le format de charge utile PUBLISH du magasin d’états est inspiré de RESP3, qui est le protocole sous-jacent utilisé par Redis. RESP3 encode à la fois le verbe, tel que SET ou GET, et les paramètres tels que keyName et keyValue.

Respect de la casse

Le client doit envoyer les verbes et les options en majuscules.

Format de la demande

Les demandes sont formatées comme dans l'exemple suivant. Après RESP3, * représente le nombre d’éléments d’un tableau. Le caractère $ est le nombre de caractères de la ligne suivante, à l’exclusion du CRLF de fin.

Les commandes prises en charge au format RESP3 sont GET, SET, DEL et 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>

L'exemple suivant montre les charges utiles RESP3 du magasin d'état :

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

Remarque

Notez que SET nécessite des propriétés MQTT5 supplémentaires, comme expliqué dans la section Contrôle de version et horloges logiques hybrides.

Format de la réponse

Lorsque le magasin d’états détecte une charge utile RESP3 non valide, il retourne toujours une réponse à Response Topic du demandeur. Parmi les exemples de charges utiles non valides, on peut citer une commande non valide, un RESP3 illégal ou un dépassement d'entier. Une charge utile non valide commence par la chaîne -ERR et contient plus de détails.

Remarque

Une requête GET, DELou VDEL sur une clé inexistante n’est pas considérée comme une erreur.

Si un client envoie une charge utile non valide, le magasin d'état envoie une charge utile comme dans l'exemple suivant :

-ERR syntax error

Réponse de SET

Lorsqu’une requête SET réussit, le magasin d’états retourne la charge utile suivante :

+OK<CR><LF>

Si une requête SET échoue, car une vérification de condition telle qu’elle est spécifiée dans les options de jeu NX ou NEX qui signifie que la clé ne peut pas être définie, le magasin d’états retourne la charge utile suivante :

-1<CR><LF>

Réponse de GET

Lorsqu’une requête GET est effectuée sur une clé inexistante, le magasin d’états retourne la charge utile suivante :

$-1<CR><LF>

Lorsque la clé est trouvée, le magasin d'état renvoie la valeur dans le format suivant :

${NumberOfBytes}<CR><LF>
{KEY-VALUE}

La sortie du magasin d’états qui retourne la valeur 1234 ressemble à l’exemple suivant :

$4<CR><LF>1234<CR><LF>

Réponse DEL et VDEL

Le magasin d'état renvoie le nombre de valeurs qu'il supprime lors d'une requête de suppression. Actuellement, le magasin d'état ne peut supprimer qu'une seule valeur à la fois.

:{NumberOfDeletes}<CR><LF> // Will be 1 on successful delete or 0 if the keyName is not present

Voici un exemple de résultat d’une commande DEL réussie :

:1<CR><LF>

Si une requête VDEL échoue, car la valeur spécifiée ne correspond pas à la valeur associée à la clé, le magasin d’états retourne la charge utile suivante :

-1<CR><LF>

-ERR réponses

Voici la liste actuelle des chaînes d’erreur. Votre application cliente doit gérer erreur inconnue chaînes pour prendre en charge les mises à jour du magasin d’états.

Chaîne d’erreur retournée à partir du magasin d’états Explication
le timestamp demandé est trop loin dans le temps. Vérifiez que les horloges système broker et client sont synchronisées Un timestamp demandé inattendu a été provoqué par le magasin d’état et les horloges clientes ne sont pas synchronisées.
un jeton d’authentification est requis pour cette requête Désolé, une erreur se produit si une clé est marquée avec un jeton d’escrime, mais que le client ne spécifie pas le jeton d’escrime.
le timestamp du jeton de clôture demandé est trop éloigné dans le temps. Vérifiez que les horloges système broker et client sont synchronisées Horodatage inattendu du jeton de clôture causé par la désynchronisation des horloges du magasin d’état et du client.
le jeton de clôture demandé est une version inférieure au jeton de clôture protégeant la ressource Version incorrecte du jeton de clôture demandé. Pour plus d’informations, consultez [Horloges logiques de contrôle de version et hybrides]. (horloges logiques #versioning et hybrides)
le quota a été dépassé Le magasin d’états a un quota du nombre de clés qu’il peut stocker, qui est basé sur le profil de mémoire du répartiteur MQTT spécifié.
erreur de syntaxe La charge utile envoyée n’est pas conforme à la définition du magasin d’états.
non autorisé Erreur d’autorisation
commande inconnue La commande n’est pas reconnue.
nombre d’arguments erroné Nombre incorrect d’arguments attendus.
horodatage manquant Lorsque les clients effectuent un SET, ils doivent définir la propriété utilisateur MQTT5 __ts comme un HLC représentant son horodatage.
horodatage mal formé L’horodatage dans le __ts ou le jeton d’escrime n’est pas légal.
la longueur de la clé est égale à zéro Les clés ne peuvent pas être de longueur nulle dans le magasin d’états.

Versioning et horloges logiques hybrides

Cette section décrit comment le magasin d'états gère les versions.

Versions en tant qu’horloges logiques hybrides

Le magasin d'état conserve une version pour chaque valeur qu'il stocke. Le magasin d'état pourrait utiliser un compteur à augmentation monotone pour conserver les versions. Au lieu de cela, le magasin d'état utilise une horloge logique hybride (HLC) pour représenter les versions. Pour plus d’informations, consultez les articles sur la conception originale des HLC et l’intention derrière les HLC.

Le magasin d'État utilise le format suivant pour définir les HLC :

{wallClock}:{counter}:{node-Id}

Le wallClock est le nombre de millisecondes depuis l’époque Unix. counter et node-Id fonctionnent en tant que HLC en général.

Lorsque les clients effectuent un SET, ils doivent définir la propriété utilisateur MQTT5 __ts comme un HLC représentant son timestamp, en fonction de l’horloge actuelle du client. Le magasin d'état renvoie la version de la valeur dans son message de réponse. La réponse est également spécifiée en tant que HLC et utilise également la propriété utilisateur __ts MQTT5. Le HLC renvoyé est toujours supérieur au HLC de la requête initiale.

Exemple de définition et de récupération de la version d'une valeur

Cette section présente un exemple de définition et d'obtention de la version d'une valeur.

Un client définit keyName=value. L'horloge du client est le 3 octobre à 23 h 07 : 05 GMT. La valeur de l’horloge est 1696374425000 milliseconde depuis l’époque Unix. Supposons que l'horloge du système du magasin d'état soit identique à celle du système du client. Le client effectue la commande SET comme décrit précédemment.

Le diagramme suivant illustre la commande SET :

Diagramme de la commande de magasin d’états pour définir la version d’une valeur.

La propriété __ts (timestamp) du jeu initial contient 1696374425000 comme horloge du mur du client, le compteur comme 0, et son node-Id comme CLIENT. Dans la réponse, la propriété __ts retournée par le magasin d’états contient le wallClock, le compteur incrémenté par un et le node-Id en tant que StateStore. Le magasin d’états peut retourner une valeur wallClock plus élevée si son horloge était à l’avance, en fonction de la façon dont les mises à jour HLC fonctionnent.

Cette version est également retournée sur les demandes GET, DEL et VDEL réussies. Sur ces requêtes, le client ne spécifie pas de __ts.

Le diagramme suivant illustre la commande GET :

Diagramme du magasin d’états obtenant la version d’une valeur.

Remarque

Le timestamp __ts que le magasin d’états retourne est identique à ce qu’il a retourné lors de la requête SET initiale.

Si une clé donnée est ultérieurement mise à jour avec un nouveau SET, le processus est similaire. Le client doit définir sa requête __ts en fonction de son horloge actuelle. Le magasin d’états met à jour la version de la valeur et retourne __ts, suivant les règles de mise à jour HLC.

Décalage de l’horloge

Le magasin d’états rejette un __ts (et également un __ft) qui est plus d’une minute avant l’horloge locale du magasin d’état.

Le magasin d’états accepte un __ts qui se trouve derrière l’horloge locale du magasin d’état. Comme spécifié dans l'algorithme HLC, le magasin d'état règle la version de la clé sur son horloge locale parce qu'elle est plus grande.

Jetons de verrouillage et de clôture

Cette section décrit l'objectif et l'utilisation des jetons de verrouillage et de clôture.

Background

Supposons que deux clients MQTT ou plus utilisent la mémoire d'état. Les deux clients veulent écrire sur une clé donnée. Les clients du magasin d'état ont besoin d'un mécanisme pour verrouiller la clé, de sorte qu'un seul client à la fois puisse modifier une clé donnée.

Un exemple de ce scénario se produit dans les systèmes actifs et en attente. Il peut y avoir deux clients qui effectuent la même opération, et l'opération peut inclure le même ensemble de clés de la mémoire d'état. À un moment donné, l'un des clients est actif et l'autre est prêt à prendre immédiatement le relais si le système actif se bloque ou tombe en panne. Dans l'idéal, un seul client devrait écrire dans la mémoire d'état à un moment donné. Cependant, dans les systèmes distribués, il est possible que les deux clients se comportent comme s'ils étaient actifs et qu'ils essaient simultanément d'écrire sur les mêmes clés. Ce scénario crée une condition de course.

Le magasin d'état fournit des mécanismes pour éviter cette condition de course en utilisant des jetons de clôture. Pour plus d’informations sur les jetons d’escrime et la classe de conditions de course qu’ils sont conçus pour se protéger, consultez cet article.

Obtenir un jeton de clôture

Cet exemple suppose que nous avons les éléments suivants :

  • Voir Client1 et Client2. Ces clients sont des clients de stockage d'état qui agissent comme une paire active et une paire de réserve.
  • LockName. Le nom d'une clé dans le magasin d'état qui joue le rôle de verrou.
  • ProtectedKey. La clé qui doit être protégée contre plusieurs rédacteurs.

Les clients tentent d'abord d'obtenir un verrou. Ils obtiennent un verrou en faisant un SET LockName {CLIENT-NAME} NEX PX {TIMEOUT-IN-MILLISECONDS}. Rappelez-vous des options de définition selon lesquelles l’indicateur NEX indique que le SET ne réussit que si l’une des conditions suivantes est remplie :

  • La clé était vide
  • La valeur de la clé est déjà définie sur la <valeur> et PX spécifie le délai d’expiration en millisecondes.

Supposons que Client1 va d’abord avec une requête de SET LockName Client1 NEX PX 10000. Cette requête lui donne la propriété de LockName pour 10 000 millisecondes. Si Client2 tente un SET LockName Client2 NEX ... pendant que Client1 possède le verrou, l’indicateur NEX indique que la requête Client2 échoue. Client1 doit renouveler ce verrou en envoyant la même commande SET utilisée pour acquérir le verrou, si Client1 souhaite continuer la propriété.

Remarque

Un SET NX est conceptuellement équivalent à AcquireLock().

Utiliser les jetons de clôture pour les demandes ENSEMBLE

Si Client1 réussit un SET (« AcquireLock ») sur LockName, le magasin d’états retourne la version de LockName en tant qu’horloge logique hybride (HLC) dans la propriété utilisateur __ts MQTT5.

Lorsqu’un client effectue une demande SET, il peut éventuellement inclure la propriété utilisateur MQTT5 __ft pour représenter un « jeton de clôture ». Le __ft est représenté sous la forme d’un HLC. Le jeton de clôture associé à une paire clé-valeur donnée permet de vérifier la propriété du verrou. Le jeton de clôture peut provenir de n'importe où. Pour ce scénario, il doit provenir de la version de LockName.

Le diagramme suivant montre le flux du processus de Client1 effectuant une requête SET sur LockName :

Diagramme d’un client effectuant une requête définie sur la propriété de nom de verrou.

Ensuite, Client1 utilise la propriété __ts (Property=1696374425000:1:StateStore) non modifiée comme base de la propriété __ft dans la requête de modification ProtectedKey. Comme toutes les demandes SET, le client doit définir la propriété __ts sur ProtectedKey.

Le diagramme suivant montre le flux du processus de Client1 effectuant une requête SET sur ProtectedKey :

Diagramme du client effectuant une demande définie sur la propriété de clé protégée.

Si la requête réussit, à partir de ce stade, ProtectedKey nécessite un jeton de clôture égal ou supérieur à celui spécifié dans la requête SET.

Algorithme du jeton de clôture

Le magasin d’états accepte n’importe quel HLC pour le __ts d’une paire clé-valeur, si la valeur se trouve dans l’asymétrie d’horloge maximale. Il n'en va pas de même pour les jetons de clôture.

L'algorithme de stockage d'état pour les jetons de clôture est le suivant :

  • Si une paire clé-valeur n’a pas de jeton d’authentification associé et qu’une requête SET définit __ft, le magasin d’états stocke le __ft associé à la paire clé-valeur.
  • Si un jeton de clôture est associé à une paire clé-valeur :
    • Si une requête SET n’a pas spécifié __ft, rejetez la demande.
    • Si une requête SET a spécifié un __ft qui a une valeur HLC plus ancienne que le jeton de clôture associé à la paire clé-valeur, rejetez la requête.
    • Si une requête SET a spécifié un __ft qui a une valeur HLC égale ou plus récente que le jeton de clôture associé à la paire clé-valeur, acceptez la requête. Le magasin d'état met à jour le jeton de clôture de la paire clé-valeur pour qu'il corresponde à celui défini dans la requête, s'il est plus récent.

Une fois qu’une clé est marquée avec un jeton de clôture, pour qu’une requête réussisse, les requêtes DEL et VDEL nécessitent également que la propriété __ft soit incluse. L'algorithme est identique au précédent, sauf que le jeton de clôture n'est pas stocké car la clé est supprimée.

Comportement du client

Ces mécanismes de verrouillage reposent sur le bon comportement des clients. Dans l’exemple précédent, un comportement incorrect Client2 n’a pas pu être propriétaire de LockName et a réussi à effectuer un SET ProtectedKey en choisissant un jeton de clôture plus récent que le jeton ProtectedKey. Le magasin d’états n’est pas conscient que LockName et ProtectedKey n’ont aucune relation. Par conséquent, le magasin d’états ne vérifie pas que Client2 possède réellement la valeur.

La possibilité pour les clients d'écrire des clés dont ils ne possèdent pas le verrou est un comportement indésirable. Vous pouvez vous prémunir contre ce type de comportement en mettant correctement en œuvre les clients et en utilisant l'authentification pour limiter l'accès aux clés aux seuls clients de confiance.

Notifications

Les clients peuvent s’inscrire auprès du magasin d’états pour recevoir des notifications de clés en cours de modification. Considérez le scénario dans lequel un thermostat utilise la clé de magasin d’état {thermostatName}\setPoint. D’autres clients du magasin d’états peuvent modifier la valeur de cette clé pour modifier le paramètre setPoint du thermostat. Au lieu d’interroger les modifications, le thermostat peut s’inscrire auprès du magasin d’états pour recevoir des messages lorsque {thermostatName}\setPoint est modifié.

Messages de requête KEYNOTIFY

Les clients du magasin d’état demandent au magasin d’état de surveiller les modifications d’un keyName donné en envoyant un message KEYNOTIFY. Tout comme toutes les demandes de magasin d’états, les clients publient (PUBLISH) un message QoS1 avec ce message via MQTT5 dans la rubrique système statestore/v1/FA9AE35F-2F64-47CD-9BFF-08E2B32A0FE8/command/invoke du magasin d’états.

La charge utile de la demande est de la forme suivante :

KEYNOTIFY<CR><LF>
{keyName}<CR><LF>
{optionalFields}<CR><LF>

Où :

  • KEYNOTIFY est un littéral de chaîne spécifiant la commande.
  • {keyName} est le nom de clé sur lequel écouter les notifications. Les caractères génériques ne sont actuellement pas pris en charge.
  • {optionalFields} Les valeurs de champ facultatives actuellement prises en charge sont les suivantes :
    • {STOP} S’il existe une notification existante avec le même keyName et clientId que cette demande, le magasin d’états la supprime.

L’exemple de sortie suivant montre une demande KEYNOTIFY pour surveiller la clé SOMEKEY :

*2<CR><LF>
$9<CR><LF>
KEYNOTIFY<CR><LF>
$7<CR><LF>
SOMEKEY<CR><LF>

Message de réponse KEYNOTIFY

Comme toutes les requêtes RPC du magasin d’états, le magasin d’états retourne sa réponse au Response Topic et utilise les propriétés Correlation Data spécifiées à partir de la requête initiale. Pour KEYNOTIFY, une réponse réussie indique que le magasin d’états a traité la demande. Une fois que le magasin d’états a réussi à traiter la demande, il surveille la clé du client actuel ou arrête la surveillance.

En cas de réussite, la réponse du magasin d’états est la même qu’un SET réussi.

+OK<CR><LF>

Si un client envoie une demande KEYNOTIFY SOMEKEY STOP, mais que le magasin d’états ne surveille pas cette clé, la réponse du magasin d’états est identique à la tentative de suppression d’une clé qui n’existe pas.

:0<CR><LF>

Tout autre échec suit le modèle général de rapport d’erreurs du magasin d’états :

-ERR: <DESCRIPTION OF ERROR><CR><LF>

Rubriques et cycle de vie des notifications KEYNOTIFY

Lorsqu’un keyName surveillé via KEYNOTIFY est modifié ou supprimé, le magasin d’états envoie une notification au client. La rubrique est déterminée par convention : le client ne spécifie pas la rubrique pendant le processus KEYNOTIFY.

La rubrique est définie dans l’exemple suivant. Le clientId est une représentation codée en hexadécimal en majuscules du ClientId MQTT du client qui a lancé la demande KEYNOTIFY et keyName est une représentation encodée hexadécimal de la clé qui a changé. Le magasin d’état suit les règles d’encodage Base16 du document RFC 4648 – Encodages de données Base16, Base32 et Base64 pour cet encodage.

clients/statestore/v1/FA9AE35F-2F64-47CD-9BFF-08E2B32A0FE8/{clientId}/command/notify/{keyName}

Par exemple, l’Agent MQTT publie un message NOTIFY envoyé à client-id1 avec le nom de clé modifié SOMEKEY dans la rubrique :

clients/statestore/v1/FA9AE35F-2F64-47CD-9BFF-08E2B32A0FE8/636C69656E742D696431/command/notify/534F4D454B4559`

Un client qui utilise des notifications doit SUBSCRIBE à cette rubrique et attendre la réception de SUBACK avant d’envoyer des demandes KEYNOTIFY afin qu’aucun message ne soit perdu.

Si un client se déconnecte, il doit se réinscrire à la rubrique de notification KEYNOTIFY et renvoyer la commande KEYNOTIFY pour toutes les clés qu’il doit continuer de surveiller. Contrairement aux abonnements MQTT, qui peuvent être conservés sur une session nonclean, le magasin d’états supprime en interne tous les messages KEYNOTIFY lorsqu’un client donné se déconnecte.

Format du message de notification KEYNOTIFY

Lorsqu’une clé surveillée via KEYNOTIFY est modifiée, le magasin d’états PUBLISH un message à la rubrique de notification suivant le format pour indiquer les clients du magasin d’états inscrits pour la modification.

NOTIFY<CR><LF>
{operation}<CR><LF>
{optionalFields}<CR><LF>

Les détails suivants sont inclus dans le message :

  • NOTIFY est un littéral de chaîne inclus comme premier argument dans la charge utile, indiquant qu’une notification est arrivée.
  • {operation} est l’événement qui s’est produit. Actuellement, ces opérations sont les suivantes :
    • SET la valeur a été modifiée. Cette opération ne peut se produire qu’à la suite d’une commande SET à partir d’un client de magasin d’états.
    • DEL la valeur a été supprimée. Cette opération peut se produire en raison d’une ou commande DEL ou VDEL à partir d’un client de magasin d’états.
  • optionalFields
    • Voir VALUE et {MODIFIED-VALUE}. VALUE est un littéral de chaîne indiquant que le champ suivant, {MODIFIED-VALUE}, contient la valeur sur laquelle la clé a été modifiée. Cette valeur est envoyée uniquement en réponse aux clés modifiées en raison d’un SET.

L’exemple de sortie suivant montre un message de notification envoyé lorsque la clé SOMEKEY est modifiée à la valeur abc, avec VALUE inclus, car la demande initiale a spécifié l’option 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>

Le message de notification KEYNOTIFY contient l’horodatage de la valeur au moment de la notification d’un client à propos d’une requête SET (valeur mise à jour) ou d’une requête DEL ou VDEL (valeur supprimée). L’horodatage fait partie de la propriété utilisateur __ts MQTT v5 du message. Pour plus d’informations, consultez la section Versions en tant qu’horloges logiques hybrides.