redis 事务

一、redis事务介绍

Redis中的事务(transaction)是一组命令的集合。事务同命令一样都是Redis最小的执行单位,一个事务中的命令要么都执行,要么都不执行。Redis事务的实现需要用到 MULTI EXEC 两个命令,事务开始的时候先向Redis服务器发送 MULTI 命令,然后依次发送需要在本次事务中处理的命令,最后再发送 EXEC 命令表示事务命令结束。

二、Demo

1.正常执行的情况

127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> set k1 v1
QUEUED
127.0.0.1:6379> set k2 v2
QUEUED
127.0.0.1:6379> set k3 v3
QUEUED
127.0.0.1:6379> EXEC
1) OK
2) OK
3) OK
127.0.0.1:6379> keys *
1) "k2"
2) "k3"
3) "k1"

2.取消执行的情况

127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> set k4 v4
QUEUED
127.0.0.1:6379> set k5 v5
QUEUED
127.0.0.1:6379> DISCARD
OK
127.0.0.1:6379> keys *
1) "k2"
2) "k3"
3) "k1"

我们可以看到,当执行DISCARD指令时,k4和k5没有存入内存

3.redis事务与mysql事务的不同点

3.1 非原子性表现

mysql事务内的sql是一组原子操作,要么事务内的多条sql都执行成功,要么事务内的多条sql都执行失败;但是redis事务不是原子性的,如下:虽然k2的值是v2,incr k2这个命令会失败,但是,set k4 v4 和 get k3 这两个命令还是成功了

127.0.0.1:6379> keys *
1) "k2"
2) "k1"
3) "k3"
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> set k4 v4
QUEUED
127.0.0.1:6379> get k3
QUEUED
127.0.0.1:6379> INCR k2
QUEUED
127.0.0.1:6379> EXEC
1) OK
2) "v3"
3) (error) ERR value is not an integer or out of range
127.0.0.1:6379> get k4
"v4"
127.0.0.1:6379> 

3.2 原子性表现,当指令入队列失败时,redis的事务表现为原子性,如下,set k5 v5 指令没有成功

127.0.0.1:6379> keys *
1) "k4"
2) "k2"
3) "k1"
4) "k3"
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> set k5 v5
QUEUED
127.0.0.1:6379> set k6
(error) ERR wrong number of arguments for 'set' command
127.0.0.1:6379> EXEC
(error) EXECABORT Transaction discarded because of previous errors.
127.0.0.1:6379> get k5
(nil)
127.0.0.1:6379> 

4.由于redis事务非原子性,所以当一组命令一定要原子性操作时,我们可以使用WATCH key指令,来监控一组事务中,要操作的key,从而保证数据的完整性,如下,假设,一张银行信用卡,我们设置,可刷余额为 100元,我们的欠额为0元,当我们刷卡操作时,监控balance

4.1正常执行情况:

127.0.0.1:6379> set balance 100
OK
127.0.0.1:6379> set debt 0
OK
127.0.0.1:6379> WATCH balance
OK
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> DECRBY balance 20
QUEUED
127.0.0.1:6379> INCRBY debt 20
QUEUED
127.0.0.1:6379> EXEC
1) (integer) 80
2) (integer) 20
127.0.0.1:6379> get balance
"80"
127.0.0.1:6379> get debt
"20"
127.0.0.1:6379> 

4.2 当redis事务还没有提交时,我们监控的key被改动时,事务会提交失败

127.0.0.1:6379> get balance
"80"
127.0.0.1:6379> get debt
"20"127.0.0.1:6379> WATCH balance
OK
127.0.0.1:6379> set balance 500  #假设,监控了balance,事务还没开启或开启了,没有提交的情况下,balance被更改,事务将会提交失败
OK
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> DECRBY balance 20
QUEUED
127.0.0.1:6379> INCRBY debt 20
QUEUED
127.0.0.1:6379> EXEC
(nil)
127.0.0.1:6379> get balance
"500"
127.0.0.1:6379> get debt
"20"
127.0.0.1:6379> 

 

posted @ 2016-10-30 00:03  坏~牧羊人  阅读(179)  评论(0编辑  收藏  举报