Skip to content

Commit 1898691

Browse files
committed
Apply review suggestions
1 parent a23c468 commit 1898691

File tree

4 files changed

+81
-59
lines changed

4 files changed

+81
-59
lines changed

content/commands/xadd.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -187,11 +187,13 @@ Prevents the creation of a new stream if the key does not exist. Available since
187187
Enables idempotent message processing (at-most-once production) to prevent duplicate entries. Available since Redis 8.6.
188188

189189
- `IDMPAUTO producer-id`: Automatically generates a unique idempotent ID (iid) for the specified producer-id. Redis tracks this iid to prevent duplicate messages from the same producer-id.
190-
- `IDMP producer-id idempotent-id`: Uses the specified idempotent-id for the given producer-id. If this producer-id/idempotent-id combination was already used, the command returns the idempotent-id of the existing entry instead of creating a duplicate.
190+
- `IDMP producer-id idempotent-id`: Uses the specified idempotent-id for the given producer-id. If this producer-id/idempotent-id combination was already used, the command returns the ID of the existing entry instead of creating a duplicate.
191191

192192
The producer-id identifies the source of the message, while the idempotent-id ensures uniqueness within that producer-id's message stream. Redis maintains an internal map of recent producer-id/idempotent-id combinations to detect and prevent duplicates.
193193

194-
Use [`XCFGSET`]({{< relref "/commands/xcfgset" >}}) to configure how long idempotent IDs are retained (`DURATION`) and the maximum number tracked per producer (`MAXSIZE`).
194+
Both modes can only be specified when the entry ID is `*` (auto-generated).
195+
196+
Use [`XCFGSET`]({{< relref "/commands/xcfgset" >}}) to configure how long idempotent IDs are retained (`IDMP-DURATION`) and the maximum number tracked per producer (`IDMP-MAXSIZE`).
195197

196198
See [Idempotent message processing]({{< relref "/develop/data-types/streams/idempotency" >}}) for more information.
197199

@@ -318,7 +320,7 @@ XADD mystream IDMP producer1 msg1 * field value
318320
XADD mystream IDMP producer1 msg1 * field different_value
319321
XADD mystream IDMPAUTO producer2 * field value
320322
XADD mystream IDMPAUTO producer2 * field value
321-
XCFGSET mystream DURATION 300 MAXSIZE 1000
323+
XCFGSET mystream IDMP-DURATION 300 IDMP-MAXSIZE 1000
322324
{{% /redis-cli %}}
323325

324326
## Redis Enterprise and Redis Cloud compatibility

content/commands/xcfgset.md

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ arguments:
77
type: key
88
- arguments:
99
- name: duration-token
10-
token: DURATION
10+
token: IDMP-DURATION
1111
type: pure-token
1212
- name: duration
1313
type: integer
@@ -16,7 +16,7 @@ arguments:
1616
type: block
1717
- arguments:
1818
- name: maxsize-token
19-
token: MAXSIZE
19+
token: IDMP-MAXSIZE
2020
type: pure-token
2121
- name: maxsize
2222
type: integer
@@ -59,7 +59,7 @@ reply_schema:
5959
const: OK
6060
since: 8.6.0
6161
summary: Sets the IDMP configuration parameters for a stream.
62-
syntax_fmt: XCFGSET key [DURATION duration] [MAXSIZE maxsize]
62+
syntax_fmt: XCFGSET key [IDMP-DURATION duration] [IDMP-MAXSIZE maxsize]
6363
title: XCFGSET
6464
---
6565
Sets the IDMP (Idempotent Message Processing) configuration parameters for a stream. This command configures how long idempotent IDs are retained and the maximum number of idempotent IDs tracked per producer.
@@ -74,15 +74,15 @@ The name of the stream key. The stream must already exist.
7474

7575
## Optional arguments
7676

77-
<details open><summary><code>DURATION duration</code></summary>
77+
<details open><summary><code>IDMP-DURATION duration</code></summary>
7878

79-
Sets the duration in seconds that each idempotent ID (iid) is kept in the stream's IDMP map. Valid range: 1-86400 seconds. Default: 100 seconds.
79+
Sets the duration in seconds that each idempotent ID (iid) is kept in the stream's IDMP map. Valid range: 1-86,400 seconds. Default: 100 seconds.
8080

8181
When an idempotent ID expires, it can be reused for new messages. This provides an operational guarantee that Redis will not forget an idempotency ID before the duration elapses (unless capacity is reached).
8282

8383
</details>
8484

85-
<details open><summary><code>MAXSIZE maxsize</code></summary>
85+
<details open><summary><code>IDMP-MAXSIZE maxsize</code></summary>
8686

8787
Sets the maximum number of most recent idempotent IDs kept for each producer in the stream's IDMP map. Valid range: 1-10,000 entries. Default: 100 entries.
8888

@@ -92,18 +92,18 @@ When the capacity is reached, the oldest idempotent IDs for that producer are ev
9292

9393
## Behavior
9494

95-
- Calling `XCFGSET` clears all existing producer IDMP maps for the stream
96-
- At least one of `DURATION` or `MAXSIZE` must be specified
97-
- The stream must exist before calling this command
98-
- Configuration changes apply immediately to all future IDMP operations
95+
- Calling `XCFGSET` clears all existing producer IDMP maps for the stream.
96+
- At least one of `IDMP-DURATION` or `IDMP-MAXSIZE` must be specified.
97+
- The stream must exist before calling this command.
98+
- Configuration changes apply immediately to all future IDMP operations.
9999

100100
## Examples
101101

102102
```redis-cli
103103
XADD mystream * field value
104-
XCFGSET mystream DURATION 300
105-
XCFGSET mystream MAXSIZE 1000
106-
XCFGSET mystream DURATION 600 MAXSIZE 500
104+
XCFGSET mystream IDMP-DURATION 300
105+
XCFGSET mystream IDMP-MAXSIZE 1000
106+
XCFGSET mystream IDMP-DURATION 600 IDMP-MAXSIZE 500
107107
```
108108

109109
## Return information
@@ -127,6 +127,5 @@ The command returns an error in the following cases:
127127
- **WRONGTYPE**: The key exists but is not a stream
128128
- **ERR no such key**: The stream does not exist
129129
- **ERR syntax error**: Invalid command syntax or missing required arguments
130-
- **ERR invalid duration**: Duration value is outside the valid range (1-86400)
130+
- **ERR invalid duration**: Duration value is outside the valid range (1-86,400)
131131
- **ERR invalid maxsize**: Maxsize value is outside the valid range (1-10,000)
132-

content/develop/data-types/streams/idempotency.md

Lines changed: 50 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,22 @@ weight: 10
1717

1818
In Redis 8.6, streams support idempotent message processing (at-most-once production) to prevent duplicate entries when using at-least-once delivery patterns. This feature enables reliable message submission with automatic deduplication.
1919

20+
Idempotent message processing ensures that handling the same message multiple times produces the same system state as handling it once.
21+
22+
Beginning with Redis 8.6, streams support idempotent message processing (at-most-once production) to prevent duplicate entries when producers resend messages.
23+
24+
Producers may need to resend messages under two scenarios:
25+
26+
1. Producer-Redis network issues (disconnection and reconnection).
27+
28+
If a disconnection occurs after the producer executes `XADD`, but before it receives the reply, the producer has no way of knowing if that message was delivered.
29+
30+
1. The producer crashes and restarts.
31+
32+
If the producer crashes after calling `XADD` but before receiving the reply and marking a message as delivered, after a restart, the producer has no way of knowing if that message was delivered.
33+
34+
In both cases, to guarantee that the message is added to the stream, the producer must call `XADD` again with the same message. Without idempotent message processing, a retry may result in a message being delivered twice. With idempotent message processing, producers can guarantee at-most-once production even under such scenarios.
35+
2036
A unique ID, called an idempotent ID or *iid*, is associated with each message that is added to a stream.
2137
There are two ways to assign iids:
2238

@@ -31,8 +47,8 @@ For (1), this is the producer’s responsibility, and for (2), Redis will calcul
3147
Use the [`XADD`]({{< relref "/commands/xadd" >}}) command with idempotency parameters, `IDMP` or `IDMPAUTO`:
3248

3349
```
34-
XADD mystream IDMP producer1 msg1 * field value # producer-provided iid
35-
XADD mystream IDMPAUTO producer2 * field value # Redis-generated iid
50+
XADD mystream IDMP producer-1 iid-1 * field value # producer-1 (pid) and iid-1 (iid) are provided manually
51+
XADD mystream IDMPAUTO producer-2 * field value # producer-2 (pid) is provided manually, Redis provides the iid
3652
```
3753

3854
### Manual mode (`IDMP`)
@@ -61,6 +77,13 @@ XADD mystream IDMPAUTO producer1 * field value
6177
- Content-based: The same content produces the same iid.
6278
- Performance: Slightly slower due to hash calculation.
6379

80+
For both IDMP and IDMPAUTO, each producer application is required to use the same pid after it restarts.
81+
82+
For IDMP, each producer application is responsible for:
83+
84+
- Providing a unique iid for each entry (either globally, or just for each pid).
85+
- Reusing the same (pid, iid) when resending a message (even after it restarts).
86+
6487
Here's an illustration of how message processing in Redis Streams works with and without idempotent production:
6588

6689
{{< image filename="images/dev/stream/stream-idempotency.png" alt="Idempotent message processing in Redis Streams" >}}
@@ -70,54 +93,53 @@ Here's an illustration of how message processing in Redis Streams works with and
7093
Configure idempotency settings for a stream using [`XCFGSET`]({{< relref "/commands/xcfgset" >}}):
7194

7295
```
73-
XCFGSET mystream DURATION 300 MAXSIZE 1000
96+
XCFGSET mystream IDMP-DURATION 300 IDMP-MAXSIZE 1000
7497
```
7598

7699
### Parameters
77100

78-
- `DURATION`: How long (in seconds) to retain iids (1-86400 seconds, the default is 100).
79-
- `MAXSIZE`: The maximum number of per-producer iids to track (1-10,000 entries, the default is 100).
101+
- `IDMP-DURATION`: How long (in seconds) to retain iids (1-86400 seconds, the default is 100).
102+
- `IDMP-MAXSIZE`: The maximum number of per-producer iids to track (1-10,000 entries, the default is 100).
80103

81104
### Expiration behavior
82105

83106
Idempotent IDs are removed when either condition is met:
84107

85-
- Time-based: iids expire after the configured `DURATION`.
86-
- Capacity-based: Oldest iids are evicted when `MAXSIZE` is reached.
108+
- Time-based: iids expire after the configured `IDMP-DURATION`.
109+
- Capacity-based: Oldest iids are evicted when `IDMP-MAXSIZE` is reached. Redis never keeps more than `IDMP-MAXSIZE` iids per pid. In other words, `IDMP-MAXSIZE` is *stronger* than `IDMP-DURATION`.
87110

88111
### Determine optimal configuration values
89112

90-
`DURATION` is an operational guarantee: Redis will not discard a previously sent iid for the specified duration (unless reaching `MAXSIZE` iids for that producer).
91-
If a producer application crashes and stops sending messages to Redis, Redis will keep each iid for `DURATION` seconds, after which they will be discarded.
92-
You should know how long it may take your producer application to recover from a crash and start resending messages.
93-
`DURATION` should be set accordingly.
94-
If `DURATION` is set too high, Redis will waste memory by retaining iids for a longer duration than necessary.
113+
`IDMP-DURATION` is an operational guarantee: Redis will not discard a previously sent iid for the specified duration (unless reaching `IDMP-MAXSIZE` iids for that producer).
114+
If a producer application crashes and stops sending messages to Redis, Redis will keep each iid for `IDMP-DURATION` seconds, after which they will be discarded.
115+
You should know how long it may take your producer application to recover from a crash and start resending messages, so you should set `IDMP-DURATION` accordingly.
116+
If `IDMP-DURATION` is set too high, Redis will waste memory by retaining iids for a longer duration than necessary.
95117

96-
**Example**: if a producer crashes, it may take up to 1,000 seconds until it recovers and restarts sending messages. You should set `DURATION` to 1000.
118+
**Example**: if a producer crashes, it may take up to 1,000 seconds until it recovers and restarts sending messages. You should set `IDMP-DURATION` to 1000.
97119

98120
When a producer application retrieves an `XADD` reply from Redis, it usually marks the message as *delivered* in a transaction database or log file.
99121
If the application crashes, it needs to resend undelivered messages after recovering from the crash.
100122
Since a few messages may have not been marked as delivered as a result of the crash, the application will likely resend these messages.
101123
Using iids will allow Redis to detect such duplicate messages and filter them.
102-
Setting `MAXSIZE` correctly ensures that Redis retains a sufficient number of recent iids.
103-
If `MAXSIZE` is set too high, Redis will waste memory by retaining too many iids.
124+
Setting `IDMP-MAXSIZE` correctly ensures that Redis retains a sufficient number of recent iids.
125+
If `IDMP-MAXSIZE` is set too high, Redis will waste memory by retaining too many iids.
104126
Usually this number can be very small, and often, even *one* is enough.
105-
If your application marks messages as delivered asynchronously, you should know how long it may take from the time it retrieved a `XADD` reply from Redis until the message is marked as delivered; this duration is called *mark-delay*. `MAXSIZE` should be set to
127+
If your application marks messages as delivered asynchronously, you should know how long it may take from the time it retrieved a `XADD` reply from Redis until the message is marked as delivered; this duration is called *mark-delay*. `IDMP-MAXSIZE` should be set to
106128

107129
`mark-delay [in msec] * (messages / msec) + some margin.`
108130

109-
**Example**: a producer is sending 1K msgs/sec (1 msg/msec), and takes up to 80 msec to mark each message as delivered, `MAXSIZE` should be set to `1 * 80 + margin = 100` iids.
131+
**Example**: a producer is sending 1K msgs/sec (1 msg/msec), and takes up to 80 msec to mark each message as delivered, `IDMP-MAXSIZE` should be set to `1 * 80 + margin = 100` iids.
110132

111133
## Producer isolation
112134

113135
Each producer maintains independent idempotency tracking:
114136

115137
```
116-
XADD mystream IDMP producer1 msg1 * field value # Producer 1's tracking
117-
XADD mystream IDMP producer2 msg1 * field value # Producer 2's tracking (independent)
138+
XADD mystream IDMP producer-1 iid-1 * field value # producer-1 is tracking
139+
XADD mystream IDMP producer-2 iid-1 * field value # producer-2 is tracking (independent)
118140
```
119141

120-
Producers can use the same idempotent ID without conflicts.
142+
Producers can use the same iid without conflicts, as long as long as the pids are different.
121143

122144
## Monitoring
123145

@@ -127,13 +149,13 @@ Use [`XINFO STREAM`]({{< relref "/commands/xinfo-stream" >}}) to monitor idempot
127149
XINFO STREAM mystream
128150
```
129151

130-
Returns additional fields when idempotency is begin used:
152+
Returns additional fields when idempotency is being used:
131153

132154
- `idmp-duration`: Current duration setting.
133155
- `idmp-maxsize`: Current maxsize setting.
134-
- `pids-tracked`: Number of active producers.
135-
- `iids-tracked`: Total idempotent IDs currently stored.
136-
- `iids-added`: Lifetime count of idempotent messages added.
156+
- `pids-tracked`: The number of pids currently tracked in the stream
157+
- `iids-tracked`: Total number of iids currently tracked.
158+
- `iids-added`: Lifetime count of messages with idempotent IDs.
137159
- `iids-duplicates`: Lifetime count of duplicates prevented.
138160

139161
## Best practices
@@ -142,8 +164,7 @@ Returns additional fields when idempotency is begin used:
142164

143165
Use globally unique, persistent producer IDs:
144166

145-
- Recommended: UUID v4 for global uniqueness.
146-
- Alternative: `hostname:process_id` or application-assigned IDs.
167+
- Recommended: Use short producer IDs to save memory and increase performance.
147168
- Persistence: Use the same producer ID after restarts to maintain idempotency tracking.
148169

149170
### Configuration tuning
@@ -168,13 +189,13 @@ Idempotency introduces minimal overhead:
168189
- Memory: <1.5% additional memory usage.
169190
- Latency: Negligible impact on per-operation latency.
170191

171-
Manual mode (IDMP) is slightly faster than automatic mode (IDMPAUTO) due to avoiding hash calculation.
192+
Manual mode (IDMP) is slightly faster than automatic mode (IDMPAUTO) since it avoids hash calculations.
172193

173194
## Persistence
174195

175196
Idempotency tracking persists across Redis restarts:
176197

177198
- RDB/AOF: All producer-idempotent ID pairs are saved.
178199
- Recovery: Tracking remains active after restart.
179-
- Configuration: `DURATION` and `MAXSIZE` settings persist.
180-
- Important: Running `XCFGSET` clears all existing tracking data. Use without `DURATION` and `MAXSIZE` to clear data.
200+
- Configuration: `IDMP-DURATION` and `IDMP-MAXSIZE` settings persist.
201+
- Important: Executing `XCFGSET` with different `IDMP-DURATION` or `IDMP-MAXSIZE` values than the current values for a particular key clears its IDMP map.

0 commit comments

Comments
 (0)