6.5 KiB
1) Data model & basics
-
A queue is a List at key
queue:<name>
. -
Common patterns:
- Producer:
LPUSH queue item
(orRPUSH
) - Consumer (non-blocking):
RPOP queue
(orLPOP
) - Consumer (blocking):
BRPOP queue timeout
(orBLPOP
)
- Producer:
-
If a key doesn’t exist, it’s treated as an empty list; push creates the list; when the last element is popped, the key is deleted. ([Redis][1])
2) Commands to implement (queues via Lists)
LPUSH / RPUSH
Prepend/append one or more elements. Create the list if it doesn’t exist. Return: Integer = new length of the list.
Syntax
LPUSH key element [element ...]
RPUSH key element [element ...]
RESP (example)
*3\r\n$5\r\nLPUSH\r\n$5\r\nqueue\r\n$5\r\njob-1\r\n
:1\r\n
Refs: semantics & multi-arg ordering. ([Redis][1])
LPUSHX / RPUSHX (optional but useful)
Like LPUSH/RPUSH, but only if the list exists. Return: Integer = new length (0 if key didn’t exist).
LPUSHX key element [element ...]
RPUSHX key element [element ...]
Refs: command index. ([Redis][2])
LPOP / RPOP
Remove & return one (default) or up to COUNT elements since Redis 6.2. If the list is empty or missing, Null is returned (Null Bulk or Null Array if COUNT>1). Return:
- No COUNT: Bulk String or Null Bulk.
- With COUNT: Array of Bulk Strings (possibly empty) or Null Array if key missing.
Syntax
LPOP key [count]
RPOP key [count]
RESP (no COUNT)
*2\r\n$4\r\nRPOP\r\n$5\r\nqueue\r\n
$5\r\njob-1\r\n # or $-1\r\n if empty
RESP (COUNT=2)
*3\r\n$4\r\nLPOP\r\n$5\r\nqueue\r\n$1\r\n2\r\n
*2\r\n$5\r\njob-2\r\n$5\r\njob-3\r\n # or *-1\r\n if key missing
Refs: LPOP w/ COUNT; general pop semantics. ([Redis][3])
BLPOP / BRPOP (blocking consumers)
Block until an element is available in any of the given lists or until timeout
(seconds, double, 0
= forever).
Return on success: Array [key, element].
Return on timeout: Null Array.
Syntax
BLPOP key [key ...] timeout
BRPOP key [key ...] timeout
RESP
*3\r\n$5\r\nBRPOP\r\n$5\r\nqueue\r\n$1\r\n0\r\n # block forever
# Success reply
*2\r\n$5\r\nqueue\r\n$5\r\njob-4\r\n
# Timeout reply
*-1\r\n
Implementation notes
- If any listed key is non-empty at call time, reply immediately from the first non-empty key by the command’s key order.
- Otherwise, put the client into a blocked state (register per-key waiters). On any
LPUSH/RPUSH
to those keys, wake the earliest waiter and serve it atomically. - If timeout expires, return Null Array and clear the blocked state. Refs: timeout semantics and return shape. ([Redis][4])
LMOVE / BLMOVE (atomic move; replaces RPOPLPUSH/BRPOPLPUSH)
Atomically pop from one side of source
and push to one side of destination
.
- Use for reliable queues (move to a processing list).
BLMOVE
blocks likeBLPOP
whensource
is empty.
Syntax
LMOVE source destination LEFT|RIGHT LEFT|RIGHT
BLMOVE source destination LEFT|RIGHT LEFT|RIGHT timeout
Return: Bulk String element moved, or Null if source
empty (LMOVE); BLMOVE
blocks/Null on timeout.
RESP (LMOVE RIGHT->LEFT)
*5\r\n$5\r\nLMOVE\r\n$6\r\nsource\r\n$3\r\ndst\r\n$5\r\nRIGHT\r\n$4\r\nLEFT\r\n
$5\r\njob-5\r\n
Notes
- Prefer
LMOVE/BLMOVE
over deprecatedRPOPLPUSH/BRPOPLPUSH
. - Pattern: consumer
LMOVE queue processing RIGHT LEFT
→ work →LREM processing 1 <elem>
to ACK; a reaper can requeue stale items. Refs: LMOVE/BLMOVE behavior and reliable-queue pattern; deprecation of RPOPLPUSH. ([Redis][5])
(Compat: you can still implement RPOPLPUSH source dest
and BRPOPLPUSH source dest timeout
, but mark them deprecated and map to LMOVE/BLMOVE.) ([Redis][6])
LLEN (length)
Useful for metrics/backpressure.
LLEN key
RESP
*2\r\n$4\r\nLLEN\r\n$5\r\nqueue\r\n
:3\r\n
Refs: list overview mentioning LLEN. ([Redis][7])
LREM (ack for “reliable” processing)
Remove occurrences of element
from the list (head→tail scan).
Use count=1
to ACK a single processed item from processing
.
LREM key count element
RESP
*4\r\n$4\r\nLREM\r\n$9\r\nprocessing\r\n$1\r\n1\r\n$5\r\njob-5\r\n
:1\r\n
Refs: reliable pattern mentions LREM to ACK. ([Redis][5])
LTRIM (bounded queues / retention)
Keep only [start, stop]
range; everything else is dropped.
Use to cap queue length after pushes.
LTRIM key start stop
RESP
*4\r\n$5\r\nLTRIM\r\n$5\r\nqueue\r\n$2\r\n0\r\n$3\r\n999\r\n
+OK\r\n
Refs: list overview includes LTRIM for retention. ([Redis][7])
LRANGE / LINDEX (debugging / peeking)
LRANGE key start stop
→ Array of elements (non-destructive).LINDEX key index
→ one element or Null.
These aren’t required for queue semantics, but handy. ([Redis][7])
3) Errors & types
-
Wrong type:
-WRONGTYPE Operation against a key holding the wrong kind of value\r\n
-
Non-existing key:
- Push: creates the list (returns new length).
- Pop (non-blocking): returns Null.
- Blocking pop: Null Array on timeout. ([Redis][1])
4) Blocking engine (implementation sketch)
- Call time: scan keys in user order. If a non-empty list is found, pop & reply immediately.
- Otherwise: register the client as blocked on those keys with
deadline = now + timeout
(or infinite). - On push to any key: if waiters exist, wake one (FIFO) and serve its pop atomically with the push result.
- On timer: for each blocked client whose deadline passed, reply
Null Array
and clear state. - Connection close: remove from any wait queues.
Refs for timeout/block semantics. ([Redis][4])
5) Reliable queue pattern (recommended)
- Consume:
LMOVE queue processing RIGHT LEFT
(orBLMOVE ... 0
). - Process the job.
- ACK:
LREM processing 1 <job>
when done. - Reaper: auxiliary task that detects stale jobs (e.g., track job IDs + timestamps in a ZSET) and requeues them. (Lists don’t include timestamps; pairing with a ZSET is standard practice.) Refs: LMOVE doc’s pattern. ([Redis][5])
6) Minimal test matrix
- Push/pop happy path (both ends), with/without COUNT.
- Blocking pop: immediate availability, block + timeout, wake on push, multiple keys order, FIFO across multiple waiters.
- LMOVE/BLMOVE: RIGHT→LEFT pipeline, block + wake, cross-list atomicity, ACK via LREM.
- Type errors and key deletion on last pop.