Skip to content

Ask the HotKV docs

Answers come only from these docs and can be wrong; check the linked pages before you rely on them.

Blocking operations

Last updated

A blocking command waits on the server until there is something to return, or until its timeout passes. It lets a worker sleep until a job arrives instead of polling in a loop, which saves round trips and reacts immediately when data shows up. The connection is busy while it waits, so use a dedicated connection (or a pool) for blocking calls.

Command Waits for Timeout unit
BLPOP, BRPOP An element at the head or tail of the first non-empty list Seconds (decimals allowed)
BLMOVE An element to move from one list to another Seconds
BRPOPLPUSH Same as BLMOVE source destination RIGHT LEFT (deprecated) Seconds
BLMPOP One or more elements from the first non-empty list Seconds
BZPOPMIN, BZPOPMAX The lowest or highest scored member of the first non-empty sorted set Seconds
BZMPOP One or more members from the first non-empty sorted set Seconds
XREAD BLOCK ms New entries in one or more streams Milliseconds
XREADGROUP BLOCK ms New entries for a consumer group Milliseconds
WAIT Replicas to acknowledge this client’s writes Milliseconds
WAITAOF This client’s writes to reach the append-only file on disk Milliseconds

Producers push jobs onto a list; workers block on it.

127.0.0.1:6379> BLPOP jobs 5

The worker now waits. When a producer runs:

127.0.0.1:6379> RPUSH jobs "resize:img-881"
(integer) 1

the worker’s BLPOP returns at once with the key and the element:

1) "jobs"
2) "resize:img-881"

If nothing arrives within 5 seconds, BLPOP replies with a null array ((nil) in redis-cli; a RESP3 null on a RESP3 connection).

To make sure a job is not lost if the worker crashes after taking it, move it to a processing list atomically with BLMOVE and remove it from there once done:

127.0.0.1:6379> BLMOVE jobs jobs:processing LEFT RIGHT 5
"resize:img-881"
127.0.0.1:6379> LREM jobs:processing 1 "resize:img-881"
(integer) 1

For queues that need acknowledgements, retries and several consumer groups, a stream with XREADGROUP BLOCK is usually a better fit.

  • A timeout of 0 waits forever.
  • List and sorted set commands take seconds and accept decimals, so 0.1 is 100 ms. A negative value replies ERR timeout is negative, and text that is not a number replies ERR timeout is not a float or out of range.
  • XREAD, XREADGROUP, WAIT and WAITAOF take whole milliseconds; a value that is not an integer replies ERR timeout is not an integer or out of range.
  • Set your client library’s socket read timeout longer than the blocking timeout, or the library may give up before the server answers.

When several clients wait on the same key, they are served in the order they started waiting. A command given several keys first checks them in the order you listed them and returns from the first one that has data; if none has, it waits for whichever receives data first.

CLIENT UNBLOCK client-id [TIMEOUT | ERROR], sent from another connection, ends a blocked command. With TIMEOUT (the default) the blocked client gets its normal timeout reply; with ERROR it gets UNBLOCKED client unblocked via CLIENT UNBLOCK. CLIENT UNBLOCK replies 1 if the client was blocked and 0 otherwise. Find the client id with CLIENT LIST.

A blocking command never waits inside MULTI/EXEC, a Lua script or a function, because those run as one isolated step. It answers immediately as if its timeout had already passed: with data if there is some, otherwise with the null reply. Likewise, WAIT inside a transaction or script returns the number of replicas that have acknowledged so far without waiting.

WAIT numreplicas timeout blocks until at least numreplicas replicas have acknowledged every write this connection made so far, or the timeout passes, and replies with the number of replicas that did. On a server that is not a primary with replicas it replies 0 at once. WAITAOF numlocal numreplicas timeout does the same for the append-only file on disk, locally and on replicas. Neither makes a write durable by itself: they tell you how far it got, so your code can decide what to do. See Replication and Persistence.

All the keys of one blocking command must hash to the same slot, served by the node you send it to, as for any multi-key command. Use a hash tag, such as jobs:{eu}:high and jobs:{eu}:low, to block on several queues at once.

If the slot a client is waiting on moves to another node while it waits (a resharding or a failover), HotKV ends the wait with a MOVED redirect to the new owner, or with CLUSTERDOWN if the cluster goes down. The client should then retry, just as for any redirected command.

The blocking commands, their timeouts, replies and errors follow Redis 7. The only difference is the MOVED reply blocked clients get when their primary is demoted, described above.