Welcome back! In the previous lesson, we explored Redis Pipelines, which optimize command execution by batching multiple commands. Today, we’ll focus on Redis Transactions, a powerful feature that queues a group of commands for execution in a single, sequential operation.
By the end of this lesson, you’ll understand how to implement transactions in Redis using Java and Jedis.
Redis Transactions allow you to queue multiple commands and then execute them sequentially once you commit (using EXEC
). This is often described as an atomic operation, but it’s important to note:
- Atomic Execution: Commands within a transaction are sent to Redis as a block.
- (Partial) All or Nothing: If a command fails at queue time (e.g., invalid command), the entire transaction is discarded. However, if a command fails at runtime (e.g., type error), Redis will still execute the other commands.
- Isolation: Transactions prevent other clients from executing commands on the keys being modified until the transaction completes.
- Queuing of Commands: Commands are queued after a transaction is initiated with
MULTI
and only execute onEXEC
.
In short, Redis discards the entire transaction if a command cannot be queued correctly, but does not roll back commands if a runtime error occurs after the transaction is committed.
Here’s how to implement a basic transaction using Jedis in Java:
Java1// Start a transaction and queue commands 2Transaction transaction = jedis.multi(); 3 4// Add commands to the transaction 5transaction.set("key1", "value1"); 6transaction.incr("counter"); 7 8// Commit the transaction and retrieve results 9List<Object> results = transaction.exec(); 10 11// Print the transaction results 12System.out.println("Transaction results: " + results);
In this example:
- Start the Transaction: The
multi()
method begins the queuing process. - Queue Commands:
set
andincr
are added to the queue. - Commit the Transaction:
exec()
sends all queued commands to the Redis server, which executes them in order. - Retrieve Results: The server’s responses are returned in a
List<Object>
.
A typical output might look like this:
1Transaction results: [OK, 1]
OK
for theSET
command.1
for theINCR
command.
While Redis Transactions ensure commands are executed sequentially, you can still have runtime errors. This means the “all commands succeed or none do” concept is only fully true for queue-time errors:
- Runtime Errors: If you queue valid commands but one fails during execution (for example, incrementing a non-numeric key), Redis will still execute the other commands. The failed command returns an error.
For instance:
Java1// Example of a runtime error in a transaction 2transaction.set("key2", "value2"); 3transaction.incr("key2"); // Will fail at runtime since "key2" is not numeric 4List<Object> results = transaction.exec(); 5System.out.println("Transaction results: " + results);
Here, the SET
command succeeds while the INCR
command fails, proving the entire transaction is not discarded for a runtime error.
You may discard a transaction before committing if something changes your mind:
Java1// Start a transaction 2Transaction transaction = jedis.multi(); 3transaction.set("tempKey", "tempValue"); 4 5// Discard the transaction 6transaction.discard(); 7System.out.println("Transaction discarded.");
This clears any queued commands and exits transaction mode before any commands are executed.
- Transactions: Queue commands under
MULTI
/EXEC
, with partial atomicity—if a command is invalid at queue time, the entire transaction is discarded. No rollback occurs on runtime errors, but other commands still succeed. - Pipelines: Batch multiple commands to reduce round trips. They don’t guarantee sequential isolation or partial atomicity. Commands execute faster but independently—errors in one do not affect the rest.
Transactions remain crucial for data consistency and simplifying workflows:
- Sequential Execution: Avoids interleaving from other clients once you call
EXEC
. - Simplified Logic: Group multiple dependent commands rather than juggling them in separate operations.
- Partial Atomicity: If a command can’t be queued, nothing is executed. Runtime errors don’t cancel the entire transaction.
With these fundamentals covered, you’re ready to apply Redis Transactions in your own code. Next, let’s move on to the practice section to experiment with Redis Transactions hands-on!