Tillståndslagerprotokoll
Tillståndsarkivet är ett distribuerat lagringssystem i Azure IoT Operations-klustret. Tillståndsarkivet erbjuder samma garantier för hög tillgänglighet som MQTT-meddelanden i MQTT-asynkron meddelandekö. Enligt riktlinjerna för MQTT5/RPC-protokollet bör klienter använda MQTT5 för att interagera med tillståndsarkivet. Den här artikeln innehåller protokollvägledning för utvecklare som behöver implementera sina egna tillståndsarkivklienter.
Översikt
Tillståndsarkivet har stöd för följande kommandon:
SET
<keyName><keyValue><setOptions>GET
<keyName>DEL
<keyName>VDEL
<keyName><keyValue> ## Tar bort ett angivet <keyName> om och endast om dess värde är <keyValue>
Protokollet använder följande modell för begäran-svar:
- Begäran. Klienter publicerar en begäran till ett väldefinierat tillståndsarkivsystemavsnitt. För att publicera begäran använder klienterna de nödvändiga egenskaperna och nyttolasten som beskrivs i följande avsnitt.
- Response. Tillståndsarkivet bearbetar begäran asynkront och svarar på det svarsämne som klienten ursprungligen angav.
Följande diagram visar den grundläggande vyn för begäran och svaret:
Tillståndslagersystemämne, QoS och nödvändiga MQTT5-egenskaper
För att kommunicera med tillståndsarkivet måste klienterna uppfylla följande krav:
- Använd MQTT5. Mer information finns i MQTT 5-specifikationen.
- Använd QoS 1 (tjänstkvalitetsnivå 1). QoS 1 beskrivs i MQTT 5-specifikationen.
- Ha en klocka som ligger inom en minut från MQTT-mäklarens klocka.
För att kommunicera med tillståndsarkivet måste PUBLISH
klienterna begära till systemavsnittet statestore/v1/FA9AE35F-2F64-47CD-9BFF-08E2B32A0FE8/command/invoke
. Eftersom tillståndsarkivet är en del av Azure IoT Operations gör det ett implicit SUBSCRIBE
till det här avsnittet vid start.
Följande MQTT5-egenskaper krävs för att skapa en begäran. Om dessa egenskaper inte finns eller om begäran inte är av typen QoS 1 misslyckas begäran.
- Svarsämne. Tillståndsarkivet svarar på den första begäran med det här värdet. Vi rekommenderar att du formaterar svarsämnet som
clients/{clientId}/services/statestore/_any_/command/invoke/response
. Det är inte tillåtet att ange svarsämnet somstatestore/v1/FA9AE35F-2F64-47CD-9BFF-08E2B32A0FE8/command/invoke
eller som ett som börjar medclients/statestore/v1/FA9AE35F-2F64-47CD-9BFF-08E2B32A0FE8
i en begäran om tillståndsarkiv. Tillståndsarkivet kopplar från MQTT-klienter som använder ett ogiltigt svarsämne. - Korrelationsdata. När tillståndslagret skickar ett svar innehåller det korrelationsdata för den första begäran.
Följande diagram visar en utökad vy över begäran och svaret:
Kommandon som stöds
Kommandona SET
, GET
och DEL
beter sig som förväntat.
De värden som kommandouppsättningarna SET
och GET
kommandot hämtar är godtyckliga binära data. Storleken på värdena begränsas endast av den maximala MQTT-nyttolaststorleken och resursbegränsningarna för MQTT-koordinatorn och klienten.
SET
Alternativ
Kommandot SET
innehåller fler valfria flaggor utöver grundläggande keyValue
och keyName
:
NX
. Tillåter att nyckeln endast anges om den inte redan finns.NEX <value>
. Tillåter att nyckeln endast anges om nyckeln inte finns eller om nyckelns värde redan är inställt på <värde>. FlagganNEX
används vanligtvis för en klient som förnyar förfallodatumet (PX
) för en nyckel.PX
. Hur länge nyckeln ska finnas kvar innan den upphör att gälla, i millisekunder.
VDEL
Alternativ
Kommandot VDEL
är ett specialfall för DEL
kommandot. DEL
tar ovillkorligt bort den angivna keyName
. VDEL
kräver ett annat argument med namnet keyValue
. VDEL
tar bara bort angiven keyName
om den har samma keyValue
.
Nyttolastformat
Nyttolastformatet för tillståndsarkivet PUBLISH
är inspirerat av RESP3, som är det underliggande protokollet som Redis använder. RESP3 kodar både verbet, till exempel SET
eller GET
, och parametrarna som keyName
och keyValue
.
Skiftlägeskänslig
Klienten måste skicka både verben och alternativen i versaler.
Begärandeformat
Begäranden formateras som i följande exempel. Efter RESP3 *
representerar antalet objekt i en matris. Tecknet $
är antalet tecken på följande rad, exklusive den avslutande CRLF:en.
Kommandon som stöds i RESP3-format är GET
, SET
, DEL
och 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>
Följande exempelutdata visar resp3-nyttolaster för tillståndsarkiv:
*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>
Kommentar
SET
kräver ytterligare MQTT5-egenskaper, enligt beskrivningen i avsnittet Versionshantering och logiska hybridklockor.
Svarsformat
När tillståndsarkivet identifierar en ogiltig RESP3-nyttolast returnerar den fortfarande ett svar på beställarens Response Topic
. Exempel på ogiltiga nyttolaster är ett ogiltigt kommando, ett olagligt RESP3- eller heltalsspill. En ogiltig nyttolast börjar med strängen -ERR
och innehåller mer information.
Kommentar
En GET
, DEL
, eller VDEL
begäran om en obefintlig nyckel anses inte vara ett fel.
Om en klient skickar en ogiltig nyttolast skickar tillståndsarkivet en nyttolast som i följande exempel:
-ERR syntax error
SET
svar
När en SET
begäran lyckas returnerar tillståndsarkivet följande nyttolast:
+OK<CR><LF>
Om en SET-begäran misslyckas på grund av att en villkorskontroll som anges i NX- eller NEX-uppsättningsalternativen innebär att nyckeln inte kan anges, returnerar tillståndsarkivet följande nyttolast:
-1<CR><LF>
GET
svar
När en GET
begäran görs på en obefintlig nyckel returnerar tillståndsarkivet följande nyttolast:
$-1<CR><LF>
När nyckeln hittas returnerar tillståndsarkivet värdet i följande format:
${NumberOfBytes}<CR><LF>
{KEY-VALUE}
Utdata från tillståndsarkivet som returnerar värdet 1234
ser ut som i följande exempel:
$4<CR><LF>1234<CR><LF>
DEL
och VDEL
svar
Tillståndsarkivet returnerar det antal värden som tas bort i en borttagningsbegäran. För närvarande kan tillståndsarkivet bara ta bort ett värde i taget.
:{NumberOfDeletes}<CR><LF> // Will be 1 on successful delete or 0 if the keyName is not present
Följande utdata är ett exempel på ett lyckat DEL
kommando:
:1<CR><LF>
Om en VDEL-begäran misslyckas eftersom det angivna värdet inte matchar värdet som är associerat med nyckeln returnerar tillståndsarkivet följande nyttolast:
-1<CR><LF>
-ERR
Svaren
Följande är den aktuella listan över felsträngar. Klientprogrammet bör hantera okända felsträngar för att stödja uppdateringar av tillståndsarkivet.
Felsträng som returneras från tillståndsarkivet | Förklaring |
---|---|
Tidsstämpeln för begäran är för långt framöver. se till att klient- och asynkroniseringssystemets klockor synkroniseras | Oväntad tidsstämpel för begäran som orsakas av tillståndsarkivet och klientklockorna är inte synkroniserade. |
en stängseltoken krävs för den här begäran | Ett fel uppstår om en nyckel har markerats med en stängseltoken, men klienten inte anger fäktningstoken. |
Tidsstämpeln för begärandefäktningstoken är för långt i framtiden. se till att klient- och asynkroniseringssystemets klockor synkroniseras | Oväntad tidsstämpel för fäktningstoken som orsakas av tillståndsarkivet och klientklockorna är inte synkroniserade. |
begärandefäktningstoken är en lägre version som fäktningstoken skyddar resursen | Felaktig version av begärandefäktningstoken. Mer information finns i [Versionshantering och logiska hybridklockor]. (#versioning-and-hybrid-logical-clocks) |
kvoten har överskridits | Tillståndsarkivet har en kvot för hur många nycklar det kan lagra, vilket baseras på minnesprofilen för den MQTT-asynkron meddelandekö som har angetts. |
Syntaxfel | Nyttolasten som skickas överensstämmer inte med tillståndsarkivets definition. |
inte auktoriserad | Auktoriseringsfel |
okänt kommando | Kommandot känns inte igen. |
fel antal argument | Felaktigt antal förväntade argument. |
tidsstämpel saknas | När klienter utför en SET måste de ange MQTT5-användaregenskapen __ts som ett HLC som representerar tidsstämpeln. |
felformaterad tidsstämpel | Tidsstämpeln i __ts eller fäktningstoken är inte laglig. |
nyckellängden är noll | Nycklar får inte vara nolllängd i tillståndsarkivet. |
Versionshantering och logiska hybridklockor
I det här avsnittet beskrivs hur tillståndsarkivet hanterar versionshantering.
Versioner som logiska hybridklockor
Tillståndsarkivet har en version för varje värde som lagras. Tillståndsarkivet kan använda en monotont ökande räknare för att underhålla versioner. I stället använder tillståndsarkivet en hybrid logisk klocka (HLC) för att representera versioner. Mer information finns i artiklarna om den ursprungliga designen av HLCs och avsikten bakom HLCs.
Tillståndsarkivet använder följande format för att definiera HLC:er:
{wallClock}:{counter}:{node-Id}
wallClock
Är antalet millisekunder sedan Unix-epoken. counter
och node-Id
arbeta som HLCs i allmänhet.
När klienter gör en SET
måste de ange MQTT5-användaregenskapen __ts
som en HLC som representerar tidsstämpeln, baserat på klientens aktuella klocka. Tillståndsarkivet returnerar versionen av värdet i svarsmeddelandet. Svaret anges också som ett HLC och använder även användaregenskapen __ts
MQTT5. Det returnerade HLC:t är alltid större än HLC för den första begäran.
Exempel på hur du ställer in och hämtar ett värdes version
Det här avsnittet visar ett exempel på hur du ställer in och hämtar versionen för ett värde.
En klient anger keyName=value
. Klientklockan är 3 oktober, 23:07:05 GMT. Klockvärdet är 1696374425000
millisekunder sedan Unix-epoken. Anta att tillståndsarkivets systemklocka är identisk med klientsystemklockan. Klienten utför kommandot enligt beskrivningen SET
tidigare.
Följande diagram illustrerar SET
kommandot:
Egenskapen __ts
(tidsstämpel) på den ursprungliga uppsättningen innehåller som klientens 1696374425000
väggklocka, räknaren som 0
och dess nod-ID som CLIENT
. I svaret innehåller egenskapen __ts
som tillståndsarkivet returnerar wallClock
, räknaren som ökas med en och nod-ID:t som StateStore
. Tillståndsarkivet kan returnera ett högre wallClock
värde om klockan ligger före, baserat på hur HLC-uppdateringar fungerar.
Den här versionen returneras också vid lyckade GET
, DEL
och VDEL
begäranden. På dessa begäranden anger klienten inte en __ts
.
Följande diagram illustrerar GET
kommandot:
Kommentar
Tidsstämpeln __ts
som tillståndsarkivet returnerar är samma som den som returnerades för den första SET
begäran.
Om en viss nyckel senare uppdateras med en ny SET
är processen liknande. Klienten bör ange sin begäran __ts
baserat på den aktuella klockan. Tillståndsarkivet uppdaterar värdets version och returnerar __ts
, enligt HLC-uppdateringsreglerna.
Förskjutning av klockan
Tillståndslagret avvisar en __ts
(och även en __ft
) som ligger mer än en minut före den lokala klockan i delstatsarkivet.
Tillståndsarkivet accepterar en __ts
som ligger bakom den lokala klockan för delstatsarkivet. Enligt HLC-algoritmen anger tillståndsarkivet versionen av nyckeln till den lokala klockan eftersom den är större.
Låsnings- och fäktningstoken
I det här avsnittet beskrivs syftet med och användningen av lås- och fäktningstoken.
Bakgrund
Anta att det finns två eller flera MQTT-klienter som använder tillståndsarkivet. Båda klienterna vill skriva till en viss nyckel. Tillståndsarkivklienterna behöver en mekanism för att låsa nyckeln så att endast en klient i taget kan ändra en viss nyckel.
Ett exempel på det här scenariot inträffar i aktiva system och väntelägessystem. Det kan finnas två klienter som båda utför samma åtgärd, och åtgärden kan innehålla samma uppsättning tillståndslagringsnycklar. Vid en viss tidpunkt är en av klienterna aktiv och den andra är redo att omedelbart ta över om det aktiva systemet låser sig eller kraschar. Helst bör endast en klient skriva till tillståndsarkivet vid en viss tidpunkt. I distribuerade system är det dock möjligt att båda klienterna kan bete sig som om de är aktiva och samtidigt försöka skriva till samma nycklar. Det här scenariot skapar ett konkurrensvillkor.
Tillståndsarkivet innehåller mekanismer för att förhindra det här konkurrenstillståndet med hjälp av stängseltoken. Mer information om stängseltoken och vilken klass av rasförhållanden de är utformade för att skydda sig mot finns i den här artikeln.
Hämta en stängseltoken
Det här exemplet förutsätter att vi har följande element:
Client1
ochClient2
. Dessa klienter är tillståndsarkivklienter som fungerar som ett aktivt och väntelägespar.LockName
. Namnet på en nyckel i tillståndsarkivet som fungerar som lås.ProtectedKey
. Nyckeln som måste skyddas från flera skrivare.
Klienterna försöker få ett lås som det första steget. De får ett lås genom att göra en SET LockName {CLIENT-NAME} NEX PX {TIMEOUT-IN-MILLISECONDS}
. Kom ihåg från Ange alternativ att NEX
flaggan innebär att endast SET
lyckas om något av följande villkor uppfylls:
- Nyckeln var tom
- Nyckelns värde är redan inställt på <värde> och
PX
anger tidsgränsen i millisekunder.
Anta att Client1
det går först med en begäran om SET LockName Client1 NEX PX 10000
. Den här begäran ger den ägarskap LockName
för i 10 000 millisekunder. Om Client2
ett försök görs ett SET LockName Client2 NEX ...
tag Client1
äger låset NEX
innebär flaggan att Client2
begäran misslyckas. Client1
måste förnya det här låset genom att skicka samma SET
kommando som används för att hämta låset, om Client1
du vill fortsätta ägarskapet.
Kommentar
A SET NX
är begreppsmässigt likvärdigt med AcquireLock()
.
Använda fäktningstoken på SET-begäranden
När Client1
gör en SET
("AcquireLock") på LockName
returnerar tillståndsarkivet versionen av LockName
som en hybrid logisk klocka (HLC) i MQTT5-användaregenskapen __ts
.
När en klient utför en SET
begäran kan den inkludera MQTT5-användaregenskapen __ft
för att representera en "fäktningstoken". __ft
representeras som en HLC. Fäktningstoken som är associerad med ett visst nyckel/värde-par ger kontroll av låsägarskap. Stängseltoken kan komma var som helst. I det här scenariot bör det komma från versionen av LockName
.
Följande diagram visar processen Client1
för att göra en SET
begäran på LockName
:
Client1
Därefter använder egenskapen __ts
(Property=1696374425000:1:StateStore
) oförändrad som grund __ft
för egenskapen i begäran för att ändra ProtectedKey
. Precis som alla SET
begäranden måste klienten ange __ts
egenskapen ProtectedKey
för .
Följande diagram visar processen Client1
för att göra en SET
begäran på ProtectedKey
:
Om begäran lyckas kräver från och med ProtectedKey
nu en stängseltoken som är lika med eller större än den som anges i SET
begäran.
Algoritm för stängseltoken
Tillståndsarkivet accepterar alla HLC:er för __ts
ett nyckel/värde-par, om värdet ligger inom den maximala klocksnedvridningen. Samma sak gäller dock inte för stängseltoken.
Tillståndslagringsalgoritmen för stängseltoken är följande:
- Om ett nyckel/värde-par inte har någon stängseltoken associerad med den och en
SET
begärandeuppsättningar__ft
lagrar tillståndsarkivet den som är associerad__ft
med nyckel/värde-paret. - Om ett nyckel/värde-par har en stängseltoken associerad med det:
- Om en
SET
begäran inte har angetts__ft
avvisar du begäran. - Om en
SET
begäran har angett ett__ft
som har ett äldre HLC-värde än den fäktningstoken som är associerad med nyckel/värde-paret avvisar du begäran. - Om en
SET
begäran har angett ett__ft
som har ett lika stort eller nyare HLC-värde än den stängseltoken som är associerad med nyckel/värde-paret godkänner du begäran. Tillståndsarkivet uppdaterar nyckel/värde-parets fäktningstoken så att den är den som anges i begäran, om den är nyare.
- Om en
När en nyckel har markerats med en fäktningstoken måste egenskapen inkluderas för att en begäran ska lyckas DEL
och VDEL
begäranden måste __ft
också inkluderas. Algoritmen är identisk med den tidigare, förutom att fäktningstoken inte lagras eftersom nyckeln tas bort.
Klientbeteende
Dessa låsmekanismer förlitar sig på att klienterna är väluppfostrade. I föregående exempel kunde ett felaktigt beteende Client2
inte äga LockName
och ändå utföra en SET ProtectedKey
genom att välja en fäktningstoken som är nyare än ProtectedKey
token. Tillståndsarkivet är inte medvetet om det LockName
och ProtectedKey
har någon relation. Därför utför inte tillståndsarkivet någon verifiering som Client2
faktiskt äger värdet.
Klienter som kan skriva nycklar som de faktiskt inte äger låset för är oönskat beteende. Du kan skydda mot sådana klienters beteende genom att implementera klienter korrekt och använda autentisering för att begränsa åtkomsten till nycklar till betrodda klienter.
Meddelanden
Klienter kan registrera sig i tillståndsarkivet för att ta emot meddelanden om nycklar som ändras. Tänk dig scenariot där en termostat använder tillståndslagringsnyckeln {thermostatName}\setPoint
. Andra tillståndsarkivklienter kan ändra nyckelns värde för att ändra termostatens setPoint. I stället för att söka efter ändringar kan termostaten registrera sig hos tillståndsarkivet för att ta emot meddelanden när {thermostatName}\setPoint
ändras.
KEYNOTIFY-begärandemeddelanden
Tillståndsarkivklienter begär att tillståndsarkivet övervakar en angiven keyName
för ändringar genom att skicka ett KEYNOTIFY
meddelande. Precis som alla begäranden om tillståndsarkiv publicerar klienterna ett QoS1-meddelande med det här meddelandet via MQTT5 till tillståndsarkivets systemämne statestore/v1/FA9AE35F-2F64-47CD-9BFF-08E2B32A0FE8/command/invoke
.
Nyttolasten för begäran har följande formulär:
KEYNOTIFY<CR><LF>
{keyName}<CR><LF>
{optionalFields}<CR><LF>
Där:
- KEYNOTIFY är en strängliteral som anger kommandot.
{keyName}
är det nyckelnamn som du vill lyssna efter meddelanden om. Jokertecken stöds inte för närvarande.{optionalFields}
De valfria fältvärden som stöds för närvarande är:{STOP}
Om det finns ett befintligt meddelande med sammakeyName
ochclientId
som den här begäran, tar tillståndsarkivet bort det.
Följande exempelutdata visar en KEYNOTIFY
begäran om att övervaka nyckeln SOMEKEY
:
*2<CR><LF>
$9<CR><LF>
KEYNOTIFY<CR><LF>
$7<CR><LF>
SOMEKEY<CR><LF>
KEYNOTIFY-svarsmeddelande
Liksom alla RPC-begäranden för tillståndslager returnerar tillståndsarkivet sitt svar på Response Topic
och använder de Correlation Data
egenskaper som anges från den första begäran. För KEYNOTIFY
anger ett lyckat svar att tillståndsarkivet bearbetade begäran. När tillståndsarkivet har bearbetat begäran övervakar den antingen nyckeln för den aktuella klienten eller stoppar övervakningen.
När tillståndsarkivet lyckas är svaret detsamma som ett lyckat SET
.
+OK<CR><LF>
Om en klient skickar en KEYNOTIFY SOMEKEY STOP
begäran men tillståndsarkivet inte övervakar den nyckeln är tillståndsarkivets svar detsamma som att försöka ta bort en nyckel som inte finns.
:0<CR><LF>
Andra fel följer tillståndsarkivets allmänna felrapporteringsmönster:
-ERR: <DESCRIPTION OF ERROR><CR><LF>
KEYNOTIFY-meddelandeämnen och livscykel
När en keyName
övervakas via KEYNOTIFY
ändras eller tas bort skickar tillståndsarkivet ett meddelande till klienten. Ämnet bestäms av konventionen – klienten anger inte ämnet under KEYNOTIFY
processen.
Ämnet definieras i följande exempel. clientId
är en hexkodad representation av MQTT ClientId för klienten som initierade KEYNOTIFY
begäran och keyName
är en hexkodad representation av nyckeln som ändrades. Tillståndslagret följer base 16-kodningsreglerna för RFC 4648 – Base16-, Base32- och Base64-datakodningar för den här kodningen.
clients/statestore/v1/FA9AE35F-2F64-47CD-9BFF-08E2B32A0FE8/{clientId}/command/notify/{keyName}
Till exempel publicerar MQTT Broker ett NOTIFY
meddelande som skickas till client-id1
med det ändrade nyckelnamnet SOMEKEY
till ämnet:
clients/statestore/v1/FA9AE35F-2F64-47CD-9BFF-08E2B32A0FE8/636C69656E742D696431/command/notify/534F4D454B4559`
En klient som använder meddelanden bör SUBSCRIBE
till det här avsnittet och vänta tills den SUBACK
tas emot innan någon KEYNOTIFY
begäran skickas så att inga meddelanden går förlorade.
Om en klient kopplas från måste den prenumerera på meddelandeavsnittet KEYNOTIFY
igen och skicka kommandot igen för alla nycklar som behövs för att fortsätta övervakningen KEYNOTIFY
. Till skillnad från MQTT-prenumerationer, som kan sparas i en icke-rensad session, tar tillståndsarkivet internt bort alla KEYNOTIFY
meddelanden när en viss klient kopplas från.
KEYNOTIFY-meddelandeformat
När en nyckel som övervakas via KEYNOTIFY
ändras kommer tillståndsarkivet att PUBLISH
skicka ett meddelande till meddelandeavsnittet enligt formatet till tillståndsarkivklienter som registrerats för ändringen.
NOTIFY<CR><LF>
{operation}<CR><LF>
{optionalFields}<CR><LF>
Följande information ingår i meddelandet:
NOTIFY
är en strängliteral som ingår som det första argumentet i nyttolasten, vilket indikerar att ett meddelande har anlänt.{operation}
är händelsen som inträffade. För närvarande är följande åtgärder:SET
-värdet ändrades. Den här åtgärden kan bara utföras som ett resultat av ettSET
kommando från en tillståndsarkivklient.DEL
värdet har tagits bort. Den här åtgärden kan inträffa på grund av ettDEL
ellerVDEL
ett kommando från en tillståndsarkivklient.
optionalFields
VALUE
och{MODIFIED-VALUE}
.VALUE
är en strängliteral som anger att nästa fält, ,{MODIFIED-VALUE}
innehåller värdet som nyckeln ändrades till. Det här värdet skickas endast som svar på att nycklar ändras på grund av enSET
.
Följande exempelutdata visar ett meddelande som skickas när nyckeln SOMEKEY
ändras till värdet abc
, med den VALUE
inkluderade eftersom den första begäran angav GET
alternativet:
*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>
Meddelandemeddelandet KEYNOTIFY
innehåller tidsstämpeln för värdet när du meddelar en klient om en SET-begäran (värdet har uppdaterats) eller när du meddelar en klient om en DEL- eller VDEL-begäran (värdet har tagits bort). Tidsstämpeln ingår som en del av meddelandets MQTT v5 User Property __ts. Mer information finns i avsnittet Versioner som logiska hybridklockor.