Redis Streams
Introduction
Redis Streams is one of the most sophisticated data types in Redis, introduced in Redis 5.0. It's designed to solve the common problem of recording and processing ordered sequences of events or messages. Unlike other Redis messaging capabilities like Pub/Sub (which provides a "fire and forget" mechanism), Streams offers persistence, consumer groups, and the ability to replay messages.
Think of Redis Streams as a log where entries are appended and identified by a timestamp. This makes them perfect for:
- Building messaging systems
- Activity feeds
- Event sourcing patterns
- IoT data collection
- Real-time analytics
Basic Concepts
Before diving deeper, let's understand the fundamental concepts of Redis Streams:
Entries
Each entry in a stream contains:
- A unique ID (typically time-based)
- One or more field-value pairs representing the data
The ID format is timestamp-sequence
, where:
timestamp
is the creation time in millisecondssequence
is a sequence number for entries created in the same millisecond
Commands Structure
Redis Streams comes with a rich set of commands, all prefixed with X
:
XADD
: Add new entriesXREAD
: Read entries from one or multiple streamsXRANGE
/XREVRANGE
: Read a range of entriesXLEN
: Get the length of a streamXDEL
: Delete specific entriesXTRIM
: Limit the stream length
Let's examine each of these commands with examples.
Working with Redis Streams
Adding Entries with XADD
The XADD
command is used to append new entries to a stream:
XADD mystream * sensor-id 1234 temperature 19.8 humidity 43.5
Output:
"1615470125872-0"
In this example:
mystream
is the stream name*
means generate an ID automatically- The rest are field-value pairs:
sensor-id
,temperature
, andhumidity
with their respective values
You can also provide a custom ID:
XADD mystream 1615470125873-0 event "button_click" user_id 1001
Reading from Streams with XREAD
To read entries from a stream:
XREAD COUNT 2 STREAMS mystream 0
Output:
1) 1) "mystream"
2) 1) 1) "1615470125872-0"
2) 1) "sensor-id"
2) "1234"
3) "temperature"
4) "19.8"
5) "humidity"
6) "43.5"
2) 1) "1615470125873-0"
2) 1) "event"
2) "button_click"
3) "user_id"
4) "1001"
In this command:
COUNT 2
limits the result to 2 entriesSTREAMS mystream 0
specifies we want to read frommystream
starting from ID0
(the beginning of the stream)
Blocking Reads
One powerful feature is the ability to block until new data arrives:
XREAD BLOCK 10000 STREAMS mystream $
This command will:
- Block for up to 10 seconds (10000 milliseconds)
- Read from
mystream
- Only return entries with IDs greater than the last ID (
$
is a special ID meaning "last ID")
Reading Ranges with XRANGE
and XREVRANGE
To read a specific range of entries:
XRANGE mystream 1615470125872-0 1615470125873-0
Or to read in reverse order:
XREVRANGE mystream 1615470125873-0 1615470125872-0
Stream Length with XLEN
To get the number of entries in a stream:
XLEN mystream
Output:
(integer) 2
Deleting Entries with XDEL
To delete specific entries:
XDEL mystream 1615470125872-0
Output:
(integer) 1
Trimming Streams with XTRIM
To limit the size of a stream:
XTRIM mystream MAXLEN 1000
This command ensures the stream won't exceed 1000 entries.
Consumer Groups
Redis Streams truly shines with its Consumer Groups feature, which enables:
- Multiple consumers reading from the same stream
- Distribution of entries among consumers
- Tracking of acknowledged and pending entries
Creating a Consumer Group
XGROUP CREATE mystream mygroup $
This creates a consumer group named mygroup
that starts reading from the last ID ($
).
Reading as Part of a Consumer Group
XREADGROUP GROUP mygroup consumer1 COUNT 1 STREAMS mystream >
Output (assuming there are unread messages):
1) 1) "mystream"
2) 1) 1) "1615470125873-0"
2) 1) "event"
2) "button_click"
3) "user_id"
4) "1001"
In this command:
GROUP mygroup consumer1
specifies the group and consumer names>
is a special ID meaning "give me entries that were never delivered to any consumer"
Acknowledging Processing with XACK
After processing an entry, you should acknowledge it:
XACK mystream mygroup 1615470125873-0
Inspecting Pending Entries
To check entries that have been delivered but not acknowledged:
XPENDING mystream mygroup
Visualizing Redis Streams
Redis Streams can be visualized as an append-only log with entries containing multiple field-value pairs:
Consumer groups can be visualized as different consumers reading from different positions:
Practical Applications
Real-time Analytics Dashboard
Redis Streams can power real-time analytics by collecting events and processing them in real-time:
// Collect user events
XADD user_events * user_id 1001 action "page_view" page "/products"
XADD user_events * user_id 1002 action "add_to_cart" product_id 5678
XADD user_events * user_id 1001 action "checkout" amount 129.99
// Process events for dashboard
XREAD COUNT 1000 BLOCK 0 STREAMS user_events 0
A background process can read these events, calculate metrics, and update a dashboard in real-time.
Chat Application
Redis Streams can be used to implement a chat system:
// User sends a message
XADD chat_room:general * user "alice" message "Hello everyone!"
// Other users read messages
XREAD BLOCK 0 STREAMS chat_room:general $
IoT Data Collection
For IoT applications, streams can efficiently collect and process sensor data:
// Sensor reports temperature
XADD sensors * device_id "temp_sensor_1" temperature 22.5 timestamp 1615470125
// Process sensor data in batches
XREADGROUP GROUP processors worker1 COUNT 100 STREAMS sensors >
Performance Considerations
When working with Redis Streams, keep these performance tips in mind:
-
Use
MAXLEN
withXADD
to automatically trim streams:XADD mystream MAXLEN ~ 10000 * field value
The
~
makes it approximate, which is more efficient. -
For high-throughput applications, batch your reads and writes.
-
Remember that consumer groups add overhead, so use them only when needed.
-
Long-running blocked
XREAD
commands might impact Redis performance under certain conditions.
Summary
Redis Streams provides a powerful and flexible way to handle time-series data, implement messaging systems, and build real-time applications. Its key features include:
- Append-only data structures for recording sequential events
- Powerful reading capabilities with blocking operations
- Consumer groups for distributed processing
- Built-in message acknowledgment and tracking
- Efficient range queries
By combining Redis Streams with other Redis data types, you can create sophisticated, high-performance applications that handle real-time data with ease.
Exercises
-
Create a simple message queue using Redis Streams:
- Producer adds messages to a stream
- Consumer reads and processes messages
- Implement acknowledgment of processed messages
-
Build a basic monitoring system that:
- Collects system metrics (CPU, memory, disk) using
XADD
- Uses
XRANGE
to analyze metrics over specific time periods - Implements alerting when metrics exceed thresholds
- Collects system metrics (CPU, memory, disk) using
-
Implement a simple chat application with multiple rooms:
- Each room is a separate stream
- Users can join rooms and read messages
- Messages show timestamp and sender information
Additional Resources
If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)