Redis的事务机制Transaction通过四个命令来完成:MULTI, EXEC, DISCARD and WATCH,建议精读链接文章对Redis事务机制有详细介绍。
Redis事务机制特性
事务(transaction)的定义从multi开始,到exec结束。
同一个事务内的多个命令,具有原子性,不会被打断
It can never happen that a request issued by another client is served in the middle of the execution of a Redis transaction. This guarantees that the commands are executed as a single isolated operation.
实例一:multi和exec之间的命令不会被其他并发处理打断,事务原子性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
clientA: 127.0.0.1:6379> multi OK 127.0.0.1:6379> set hello a QUEUED
// clientB cocurrently set hello to b
127.0.0.1:6379> get hello QUEUED 127.0.0.1:6379> exec 1) OK 2) "a"
clientB: 127.0.0.1:6379> set hello b OK
实例二:注意理解incr和set操作的区别
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
clientA: 127.0.0.1:6379> set hello 1 OK
127.0.0.1:6379> multi OK 127.0.0.1:6379> incr hello // QUEUED // clientB cocurrently set hello to 22 127.0.0.1:6379> get hello QUEUED 127.0.0.1:6379> exec 1) (integer) 23 2) "23"
// clientB: 127.0.0.1:6379> set hello 22 OK
事务内的命令要么全部执行(仅指入带执行的命令队列成功),要么都不执行
Either all of the commands or none are processed, so a Redis transaction is also atomic.
127.0.0.1:6379> multi OK 127.0.0.1:6379> set hello 1 QUEUED 127.0.0.1:6379> lset hello 0 1 // 该命令可被执行,但执行失败 QUEUED 127.0.0.1:6379> exec 1) OK 2) (error) WRONGTYPE Operation against a key holding the wrong kind of value 127.0.0.1:6379> get hello // 事务中的第一步执行成功 "1"
// clientA 127.0.0.1:6379> watch hello OK 127.0.0.1:6379> multi OK // clientB cocurrently set hello to 33 127.0.0.1:6379> set hello 2 QUEUED 127.0.0.1:6379> exec // watched hello changed, exec will fail (nil)
functionzpop($client, $key) { $element = null; $options = array( 'cas' => true, // Initialize with support for CAS operations 'watch' => $key, // Key that needs to be WATCHed to detect changes 'retry' => 3, // Number of retries on aborted transactions, after // which the client bails out with an exception. ); $client->transaction($options, function($tx)use($key, &$element){ @list($element) = $tx->zrange($key, 0, 0); if (isset($element)) { $tx->multi(); // With CAS, MULTI *must* be explicitly invoked. $tx->zrem($key, $element); } }); return $element; } $client = new Predis\Client($single_server); $zpopped = zpop($client, 'zset'); echoisset($zpopped) ? "ZPOPed $zpopped" : 'Nothing to ZPOP!', PHP_EOL;
Memcached::cas() performs a “check and set” operation, so that the item will be stored only if no other client has updated it since it was last fetched by this client. cas = check and set, 某项将在没有其他终端修改的前提下保存,即当前终端是最新一次获取此项的值
Redis的事务机制Transaction通过四个命令来完成:MULTI, EXEC, DISCARD and WATCH,建议精读链接文章对Redis事务机制有详细介绍。
Redis事务机制特性
事务(transaction)的定义从multi开始,到exec结束。
同一个事务内的多个命令,具有原子性,不会被打断
It can never happen that a request issued by another client is served in the middle of the execution of a Redis transaction. This guarantees that the commands are executed as a single isolated operation.
实例一:multi和exec之间的命令不会被其他并发处理打断,事务原子性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
clientA: 127.0.0.1:6379> multi OK 127.0.0.1:6379> set hello a QUEUED
// clientB cocurrently set hello to b
127.0.0.1:6379> get hello QUEUED 127.0.0.1:6379> exec 1) OK 2) "a"
clientB: 127.0.0.1:6379> set hello b OK
实例二:注意理解incr和set操作的区别
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
clientA: 127.0.0.1:6379> set hello 1 OK
127.0.0.1:6379> multi OK 127.0.0.1:6379> incr hello // QUEUED // clientB cocurrently set hello to 22 127.0.0.1:6379> get hello QUEUED 127.0.0.1:6379> exec 1) (integer) 23 2) "23"
// clientB: 127.0.0.1:6379> set hello 22 OK
事务内的命令要么全部执行(仅指入带执行的命令队列成功),要么都不执行
Either all of the commands or none are processed, so a Redis transaction is also atomic.
127.0.0.1:6379> multi OK 127.0.0.1:6379> set hello 1 QUEUED 127.0.0.1:6379> lset hello 0 1 // 该命令可被执行,但执行失败 QUEUED 127.0.0.1:6379> exec 1) OK 2) (error) WRONGTYPE Operation against a key holding the wrong kind of value 127.0.0.1:6379> get hello // 事务中的第一步执行成功 "1"
// clientA 127.0.0.1:6379> watch hello OK 127.0.0.1:6379> multi OK // clientB cocurrently set hello to 33 127.0.0.1:6379> set hello 2 QUEUED 127.0.0.1:6379> exec // watched hello changed, exec will fail (nil)
functionzpop($client, $key) { $element = null; $options = array( 'cas' => true, // Initialize with support for CAS operations 'watch' => $key, // Key that needs to be WATCHed to detect changes 'retry' => 3, // Number of retries on aborted transactions, after // which the client bails out with an exception. ); $client->transaction($options, function($tx)use($key, &$element){ @list($element) = $tx->zrange($key, 0, 0); if (isset($element)) { $tx->multi(); // With CAS, MULTI *must* be explicitly invoked. $tx->zrem($key, $element); } }); return $element; } $client = new Predis\Client($single_server); $zpopped = zpop($client, 'zset'); echoisset($zpopped) ? "ZPOPed $zpopped" : 'Nothing to ZPOP!', PHP_EOL;
Memcached::cas() performs a “check and set” operation, so that the item will be stored only if no other client has updated it since it was last fetched by this client. cas = check and set, 某项将在没有其他终端修改的前提下保存,即当前终端是最新一次获取此项的值