Concept Overview
Redis Publish/Subscribe (Pub/Sub) implements a messaging paradigm where senders (publishers) transmit messages to channels, and receivers (subscribers) listen for messages on those channels. A single Redis client can subscribe to multiple channels simultaneously. When a message is published to a channel, all active subscribers receive it instantly.
Essential Commands
| Command | Description |
|---|---|
| PSUBSCRIBE pattern [pattern...] | Subscribe to one or more channels matching given patterns |
| PUBSUB subcommand [argument...] | Inspect the state of the Pub/Sub subsystem |
| PUBLISH channel message | Post a message to a specified channel |
| PUNSUBSCRIBE [pattern...] | Unsubscribe from pattern-based subscriptions |
| SUBSCRIBE channel [channel...] | Subscribe to one or more specific channels |
| UNSUBSCRIBE [channel...] | Unsubscribe from specified channels |
Practical Example
Consider multiple client interactions with a channel named 'appNotifications':
# Client_A subscribes to the channel
127.0.0.1:6379> SUBSCRIBE appNotifications
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "appNotifications"
3) (integer) 1
# Client_B publishes a message
127.0.0.1:6379> PUBLISH appNotifications "Initial alert"
(integer) 1
# Client_A receives this message
# Another client joins the subscription
127.0.0.1:6379> SUBSCRIBE appNotifications
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "appNotifications"
3) (integer) 1
# Subsequent publications reach all active subscribers
127.0.0.1:6379> PUBLISH appNotifications "System update"
(integer) 2
# All subscribers receive this message
Redis Transaction Processing
Transaction Fundamentals
Redis transactions provide a mechanism for executing multiple commands as a single isolated operation. Commands within a transaction are queued and executed sequentially without interruption from other client requests. This ensures command grouping and prevents interleaved execution from different clients.
Transaction Commands: MULTI, EXEC, DISCARD
The transaction lifecycle begins with the MULTI command, which signals the start of command queuing. Subsequent commands are added to a queue but not executed immediately. The EXEC command triggers the sequential execution of all queued commands. Alternatively, DISCARD can be used to abandon the queued operation without execution.
Transaction Examples
Successful transaction execution:
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379(TX)> SET user:1001 "John Doe"
QUEUED
127.0.0.1:6379(TX)> SET balance:1001 5000
QUEUED
127.0.0.1:6379(TX)> EXEC
1) OK
2) OK
Transaction aborted due to syntax error during queuing:
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379(TX)> SET account:2002 "Jane Smith"
QUEUED
127.0.0.1:6379(TX)> SET balance:2002
(error) ERR wrong number of arguments for 'set' command
127.0.0.1:6379(TX)> EXEC
(error) EXECABORT Transaction discarded because of previous errors.
Partial failure during execution:
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379(TX)> SET counter 10
QUEUED
127.0.0.1:6379(TX)> INCR counter
QUEUED
127.0.0.1:6379(TX)> SET counter "twenty"
QUEUED
127.0.0.1:6379(TX)> INCR counter
QUEUED
127.0.0.1:6379(TX)> EXEC
1) OK
2) (integer) 11
3) OK
4) (error) ERR value is not an integer or out of range
Error Handling Behavior
Syntax errors during command queuing abort the entire transaction. Runtime errors during execution only affect the specific command that fails, while other commands in the queue continue executing. Redis does not implement automatic rollback for failed transactions.
Concurrency Control in Transactions
Typical Concurrency Scenario
Consider a bank account with an initial balance of 10000. Multiple clients attempt concurrent withdrawals: Client_A withdraws 8000, Client_B withdraws 5000, and Client_C withdraws 1000. Without proper concurrency control, race conditions can lead to incorrect final balances.
Pessimistic Locking Approach
Pessimistic locking assumes concurrent modification conflicts will occur and prevents them by acquiring locks before data access. This approach blocks other operations until the lock is released, potentially reducing concurrency but ensuring data integrity.
Optimistic Locking Strategy
Optimistic locking assumes conflicts are rare and proceeds without locks, validating data integrity only at update time. Redis implements this pattern through its WATCH mechanism, which monitors keys for modifications and aborts transactions if watched keys change.
Implementing WATCH for Conflict Resolution
The WATCH command monitors one or more keys for modifications before a transaction. If any watched key is altered by another client before the transaction executes, the transaction is aborted:
# Client_1
127.0.0.1:6379> SET account_balance 10000
OK
# Client_2
127.0.0.1:6379> WATCH account_balance
OK
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379(TX)> DECRBY account_balance 8000
QUEUED
# Concurrent modification by Client_3
127.0.0.1:6379> DECRBY account_balance 5000
(integer) 5000
# Client_2 attempts to execute
127.0.0.1:6379(TX)> EXEC
(nil) # Transaction aborted due to WATCH conflict
UNWATCH Command
The UNWATCH command clears all watched keys for the current connection. This is automatically called after EXEC or DISCARD, but can be invoked manually if needed.
Redis Transaction Characteristics
| Property | Description |
|---|---|
| Isolated Execution | Commands are serialized and executed sequentially without interruption |
| No Isolation Levels | Queued commands are not executed until EXEC, providing implicit isolation |
| No Atomicity Guarantee | Failed commands don't rollback successful ones; partial execution is possible |