TairString extends native Redis strings with a version number, enabling optimistic locking and bounded increment operations.
Overview
Native Redis strings store a key-value pair. TairString adds a version number to each key, giving you a lightweight mechanism for conflict detection without external coordination. Every write that succeeds increments the version by 1; a write that specifies the wrong version is rejected.
TairString also lets you set a minimum or maximum boundary on EXINCRBY and EXINCRBYFLOAT. If an increment would push the value outside that range, the command returns an error instead of writing the out-of-range value.
Key capabilities
Each TairString key carries a version number alongside its value.
EXSET and EXINCRBY accept a
VERoption that rejects writes when the version has changed since you last read the key—implementing compare-and-set without a separate transaction.EXINCRBY and EXINCRBYFLOAT accept
MINandMAXoptions that cap the counter at a defined range.
This module is open source. For more information, see GitHub.
How version numbers work
The following session shows how the version number evolves across a typical lifecycle: creation, a successful version-matched update, a rejected stale-version write, a compare-and-set via EXCAS, and a version-matched delete via EXCAD.
127.0.0.1:6379> EXSET foo 100
OK
127.0.0.1:6379> EXGET foo
1) "100"
2) (integer) 1
127.0.0.1:6379> EXSET foo 200 VER 1
OK
127.0.0.1:6379> EXGET foo
1) "200"
2) (integer) 2
127.0.0.1:6379> EXSET foo 300 VER 1
(error) ERR update version is stale
127.0.0.1:6379> EXCAS foo 400 2
1) OK
2)
3) (integer) 3
127.0.0.1:6379> EXCAD foo 3
(integer) 1Prerequisites
Before you begin, ensure that you have:
A Tair DRAM-based or persistent memory-optimized instance at minor version 1.2.3 or later
The latest minor version provides more features and higher stability. Update the instance to the latest minor version. For more information, see Update the minor version of an instance. For cluster or read/write splitting instances, also update the proxy nodes to the latest minor version to ensure all commands run as expected.
Usage notes
TairString data is stored on a Tair instance. Native Redis strings and TairStrings can coexist on the same Tair instance, but native Redis strings do not support the commands described in this topic.
Command summary
| Command | Syntax | Description |
|---|---|---|
| EXSET | EXSET key value [EX|PX|EXAT|PXAT time] [NX|XX] [VER|ABS version] [KEEPTTL] | Creates a TairString key if it does not exist and writes a value; overwrites the value if the key exists. |
| EXGET | EXGET key | Returns the value and version number of a TairString key. |
| EXSETVER | EXSETVER key version | Sets the version number of a TairString key. |
| EXINCRBY | EXINCRBY key num [EX|PX|EXAT|PXAT time] [NX|XX] [VER|ABS version] [MIN minval] [MAX maxval] [KEEPTTL] | Increments or decrements the value by an integer. |
| EXINCRBYFLOAT | EXINCRBYFLOAT key num [EX|PX|EXAT|PXAT time] [NX|XX] [VER|ABS version] [MIN minval] [MAX maxval] [KEEPTTL] | Increments or decrements the value by a floating-point number. |
| EXCAS | EXCAS key newvalue version | Updates the value if the version matches; returns the current value and version if it does not. |
| EXCAD | EXCAD key version | Deletes the key if the version matches. |
| DEL | DEL key [key ...] | Deletes one or more TairString keys. |
Syntax conventions
UPPERCASE: command keyword.italic: variable.[options]: optional parameter. Parameters without brackets are required.A|B: mutually exclusive options; specify only one....: the preceding parameter can be repeated.
EXSET
Time complexity| Item | Description |
|---|---|
| Syntax | EXSET key value [EX|PX|EXAT|PXAT time] [NX|XX] [VER|ABS version] [KEEPTTL] |
| O(1) | |
| Description | Creates a TairString key if it does not exist and writes a value. If the key already exists, overwrites the value. |
Parameters
key: the key to write.value: the value to write.EX time: relative expiration time in seconds.0means the key expires immediately. If omitted, the key does not expire.EXAT time: absolute expiration time in seconds (Unix timestamp).0means the key expires immediately. If omitted, the key does not expire.PX time: relative expiration time in milliseconds.0means the key expires immediately. If omitted, the key does not expire.PXAT time: absolute expiration time in milliseconds (Unix timestamp).0means the key expires immediately. If omitted, the key does not expire.NX: write only if the key does not exist.XX: write only if the key already exists.VER version: compare-and-set by version number.If the key exists: write succeeds only when the specified version matches the current version; the version is then incremented by 1. If the versions do not match, an error is returned.
If the key does not exist or its current version is 0: the VER value is ignored, the write succeeds, and the version is set to 1.
ABS version: overwrite the version unconditionally. After the write, the version equals the specified ABS value.KEEPTTL: inherit the remaining TTL (time-to-live) of the key. Cannot be combined withEX,PX,EXAT, orPXAT.
If no expiration parameter is set (EX,PX,EXAT,PXAT, orKEEPTTL), the key does not expire.
Return values
OK: the write succeeded.nil:XXwas specified but the key does not exist, orNXwas specified but the key already exists.Error: all other failures.
Example
EXSET foo bar EX 10 NX ABS 100OKEXGET
| Item | Description |
|---|---|
| Syntax | EXGET key |
| Time complexity | O(1) |
| Description | Returns the value and version number of a TairString key. |
Parameters
key: the key to read.
Return values
An array containing the value (bulk string) and the version number (integer).
Error: the key does not exist or another failure occurred.
Example
EXGET foo1) "bar"
2) (integer) 1EXSETVER
| Item | Description |
|---|---|
| Syntax | EXSETVER key version |
| Time complexity | O(1) |
| Description | Sets the version number of a TairString key. |
Parameters
key: the key to update.version: the version number to assign.
Return values
1: the version was set successfully.0: the key does not exist.Error: another failure occurred.
Example
EXSETVER foo 2(integer) 1EXINCRBY
| Item | Description |
|---|---|
| Syntax | EXINCRBY key num [EX|PX|EXAT|PXAT time] [NX|XX] [VER|ABS version] [MIN minval] [MAX maxval] [KEEPTTL] |
| Time complexity | O(1) |
| Description | Increments or decrements the value of a TairString key by an integer (LONG type). |
Parameters
key: the key to update.num: the integer amount to add (use a negative value to decrement).EX,EXAT,PX,PXAT,NX,XX,VER,ABS,KEEPTTL: same as EXSET.MIN minval: the minimum allowed value. If the result would be less thanminval, the command returns an error and does not write.MAX maxval: the maximum allowed value. If the result would exceedmaxval, the command returns an error and does not write.
If no expiration parameter is set (EX,PX,EXAT,PXAT, orKEEPTTL), the key does not expire.
Return values
The updated value (integer): the increment succeeded.
(error) ERR increment or decrement would overflow: the result would fall outside theMIN/MAXrange.Error: another failure occurred.
Example
The following example assumes EXSET foo 1 was run beforehand. The command increments foo by 100 and limits the value to a maximum of 300.
EXINCRBY foo 100 MAX 300(integer) 101Pattern: bounded counter
Use MIN and MAX to implement a rate limiter or quota counter that never exceeds its bounds:
# Initialize the counter
EXSET requests 0
# Increment on each request; reject when the limit is hit
EXINCRBY requests 1 MAX 100
# Returns (error) ERR increment or decrement would overflow when the limit is reachedEXINCRBYFLOAT
| Item | Description |
|---|---|
| Syntax | EXINCRBYFLOAT key num [EX|PX|EXAT|PXAT time] [NX|XX] [VER|ABS version] [MIN minval] [MAX maxval] [KEEPTTL] |
| Time complexity | O(1) |
| Description | Increments or decrements the value of a TairString key by a floating-point number (DOUBLE type). |
Parameters
key: the key to update.num: the floating-point amount to add (use a negative value to decrement).All other options (
EX,EXAT,PX,PXAT,NX,XX,VER,ABS,KEEPTTL,MIN,MAX): same as EXINCRBY.
If no expiration parameter is set (EX,PX,EXAT,PXAT, orKEEPTTL), the key does not expire.
Return values
The updated value: the increment succeeded.
(error) ERR increment or decrement would overflow: the result would fall outside theMIN/MAXrange.Error: another failure occurred.
Example
The following example assumes EXSET foo 1 was run beforehand.
EXINCRBYFLOAT foo 10.123(integer) 11.123EXCAS
| Item | Description |
|---|---|
| Syntax | EXCAS key newvalue version |
| Time complexity | O(1) |
| Description | Updates the value of a TairString key if the current version matches the specified version. If the versions do not match, returns the current value and version number without modifying the key. |
Parameters
key: the key to update.newvalue: the value to write if the version matches.version: the version number to compare against the current version.
Return values
["OK", "", latest_version]: the update succeeded. The empty string in the middle carries no meaning.["ERR update version is stale", current_value, current_version]: the version did not match. The key was not modified.-1: the key does not exist.Error: another failure occurred.
Example
The following example assumes EXSET foo bar was run beforehand (version = 1).
EXCAS foo bzz 11) OK
2)
3) (integer) 2Pattern: optimistic locking
Use EXCAS to implement a read-modify-write loop without locks:
# 1. Read the current value and version
EXGET mykey
# Returns: value="old", version=5
# 2. Modify locally
# 3. Write back only if the version hasn't changed
EXCAS mykey "new" 5
# If another writer changed the key, EXCAS returns the stale-version error.
# Retry from step 1.EXCAD
| Item | Description |
|---|---|
| Syntax | EXCAD key version |
| Time complexity | O(1) |
| Description | Deletes a TairString key if the current version matches the specified version. |
Parameters
key: the key to delete.version: the version number to compare against the current version.
Return values
1: the key was deleted.0: the version did not match; the key was not deleted.-1: the key does not exist.Error: another failure occurred.
Example
The following example assumes EXSET foo bar was run beforehand (version = 1).
EXCAD foo 1(integer) 1