Keyspace Notifications
Feature overview#
Keyspace notifications allow clients to subscribe to Pub/Sub channels in order to receive events affecting the KeyDB data set in some way.
Examples of events that can be received are:
- All the commands affecting a given key.
- All the keys receiving an LPUSH operation.
- All the keys expiring in the database 0.
Events are delivered using the normal Pub/Sub layer of KeyDB, so clients implementing Pub/Sub are able to use this feature without modifications.
Because KeyDB Pub/Sub is fire and forget currently there is no way to use this feature if your application demands reliable notification of events, that is, if your Pub/Sub client disconnects, and reconnects later, all the events delivered during the time the client was disconnected are lost.
In the future there are plans to allow for more reliable delivering of events, but probably this will be addressed at a more general level either bringing reliability to Pub/Sub itself, or allowing Lua scripts to intercept Pub/Sub messages to perform operations like pushing the events into a list.
Type of events#
Keyspace notifications are implemented by sending two distinct types of events for every operation affecting the KeyDB data space. For instance a DEL operation targeting the key named mykey in database 0 will trigger the delivering of two messages, exactly equivalent to the following two PUBLISH commands:
It is easy to see how one channel allows us to listen to all the events targeting the key mykey and the other channel allows to obtain information about all the keys that are target of a del operation.
The first kind of event, with keyspace prefix in the channel is called a Key-space notification, while the second, with the keyevent prefix, is called a Key-event notification.
In the above example a del event was generated for the key mykey. What happens is that:
- The Key-space channel receives as message the name of the event.
- The Key-event channel receives as message the name of the key.
It is possible to enable only one kind of notification in order to deliver just the subset of events we are interested in.
Configuration#
By default keyspace event notifications are disabled because while not very sensible the feature uses some CPU power. Notifications are enabled using the notify-keyspace-events of KeyDB.conf or via the CONFIG SET.
Setting the parameter to the empty string disables notifications. In order to enable the feature a non-empty string is used, composed of multiple characters, where every character has a special meaning according to the following table:
At least K or E should be present in the string, otherwise no event will be delivered regardless of the rest of the string.
For instance to enable just Key-space events for lists, the configuration parameter must be set to Kl, and so forth.
The string KEA can be used to enable every possible event.
Events generated by different commands#
Different commands generate different kind of events according to the following list.
DELgenerates adelevent for every deleted key.RENAMEgenerates two events, arename_fromevent for the source key, and arename_toevent for the destination key.MOVEgenerates two events, amove_fromevent for the source key, and amove_toevent for the destination key.COPYgenerates acopy_toevent.MIGRATEgenerates adelevent if the source key is removed.RESTOREgenerates arestoreevent for the key.EXPIREand all its variants (PEXPIRE,EXPIREAT,PEXPIREAT) generate anexpireevent when called with a positive timeout (or a future timestamp). Note that when these commands are called with a negative timeout value or timestamp in the past, the key is deleted and only adelevent is generated instead.SORTgenerates asortstoreevent whenSTOREis used to set a new key. If the resulting list is empty, and theSTOREoption is used, and there was already an existing key with that name, the result is that the key is deleted, so adelevent is generated in this condition.SETand all its variants (SETEX,SETNX,GETSET) generatesetevents. HoweverSETEXwill also generate anexpireevents.MSETgenerates a separatesetevent for every key.SETRANGEgenerates asetrangeevent.INCR,DECR,INCRBY,DECRBYcommands all generateincrbyevents.INCRBYFLOATgenerates anincrbyfloatevents.APPENDgenerates anappendevent.LPUSHandLPUSHXgenerates a singlelpushevent, even in the variadic case.RPUSHandRPUSHXgenerates a singlerpushevent, even in the variadic case.RPOPgenerates anrpopevent. Additionally adelevent is generated if the key is removed because the last element from the list was popped.LPOPgenerates anlpopevent. Additionally adelevent is generated if the key is removed because the last element from the list was popped.LINSERTgenerates anlinsertevent.LSETgenerates anlsetevent.LREMgenerates anlremevent, and additionally adelevent if the resulting list is empty and the key is removed.LTRIMgenerates anltrimevent, and additionally adelevent if the resulting list is empty and the key is removed.RPOPLPUSHandBRPOPLPUSHgenerate anrpopevent and anlpushevent. In both cases the order is guaranteed (thelpushevent will always be delivered after therpopevent). Additionally adelevent will be generated if the resulting list is zero length and the key is removed.LMOVEandBLMOVEgenerate anlpop/rpopevent (depending on the wherefrom argument) and anlpush/rpushevent (depending on the whereto argument). In both cases the order is guaranteed (thelpush/rpushevent will always be delivered after thelpop/rpopevent). Additionally adelevent will be generated if the resulting list is zero length and the key is removed.HSET,HSETNXandHMSETall generate a singlehsetevent.HINCRBYgenerates anhincrbyevent.HINCRBYFLOATgenerates anhincrbyfloatevent.HDELgenerates a singlehdelevent, and an additionaldelevent if the resulting hash is empty and the key is removed.SADDgenerates a singlesaddevent, even in the variadic case.SREMgenerates a singlesremevent, and an additionaldelevent if the resulting set is empty and the key is removed.SMOVEgenerates ansremevent for the source key, and ansaddevent for the destination key.SPOPgenerates anspopevent, and an additionaldelevent if the resulting set is empty and the key is removed.SINTERSTORE,SUNIONSTORE,SDIFFSTOREgeneratesinterstore,sunionostore,sdiffstoreevents respectively. In the special case the resulting set is empty, and the key where the result is stored already exists, adelevent is generated since the key is removed.ZINCRgenerates azincrevent.ZADDgenerates a singlezaddevent even when multiple elements are added.ZREMgenerates a singlezremevent even when multiple elements are deleted. When the resulting sorted set is empty and the key is generated, an additionaldelevent is generated.ZREMBYSCOREgenerates a singlezrembyscoreevent. When the resulting sorted set is empty and the key is generated, an additionaldelevent is generated.ZREMBYRANKgenerates a singlezrembyrankevent. When the resulting sorted set is empty and the key is generated, an additionaldelevent is generated.ZDIFFSTORE,ZINTERSTOREandZUNIONSTORErespectively generatezdiffstore,zinterstoreandzunionstoreevents. In the special case the resulting sorted set is empty, and the key where the result is stored already exists, adelevent is generated since the key is removed.XADDgenerates anxaddevent, possibly followed anxtrimevent when used with theMAXLENsubcommand.XDELgenerates a singlexdelevent even when multiple entries are deleted.XGROUP CREATEgenerates anxgroup-createevent.XGROUP CREATECONSUMERgenerates anxgroup-createconsumerevent.XGROUP DELCONSUMERgenerates anxgroup-delconsumerevent.XGROUP DESTROYgenerates anxgroup-destroyevent.XGROUP SETIDgenerates anxgroup-setidevent.XSETIDgenerates anxsetidevent.XTRIMgenerates anxtrimevent.PERSISTgenerates apersistevent if the expiry time associated with key has been successfully deleted.- Every time a key with a time to live associated is removed from the data set because it expired, an
expiredevent is generated. - Every time a key is evicted from the data set in order to free memory as a result of the
maxmemorypolicy, anevictedevent is generated.
IMPORTANT all the commands generate events only if the target key is really modified. For instance an SREM deleting a non-existing element from a Set will not actually change the value of the key, so no event will be generated.
If in doubt about how events are generated for a given command, the simplest thing to do is to watch yourself:
At this point use KeyDB-cli in another terminal to send commands to the KeyDB server and watch the events generated:
Timing of expired events#
Keys with a time to live associated are expired by KeyDB in two ways:
- When the key is accessed by a command and is found to be expired.
- Via a background system that looks for expired keys in the background, incrementally, in order to be able to also collect keys that are never accessed.`
The expired events are generated when a key is accessed and is found to be expired by one of the above systems, as a result there are no guarantees that the KeyDB server will be able to generate the expired event at the time the key time to live reaches the value of zero.
If no command targets the key constantly, and there are many keys with a TTL associated, there can be a significant delay between the time the key time to live drops to zero, and the time the expired event is generated.
Basically expired events are generated when the KeyDB server deletes the key and not when the time to live theoretically reaches the value of zero.
Events in a cluster#
Every node of a KeyDB cluster generates events about its own subset of the keyspace as described above. However, unlike regular Pub/Sub communication in a cluster, events' notifications are not broadcasted to all nodes. Put differently, keyspace events are node-specific. This means that to receive all keyspace events of a cluster, clients need to subscribe to each of the nodes.