redis 事务

Redis与 mysql事务的对比

  1. 开启命令:mysql 用start transaction  redis 使用 multi
  2. 执行内容:mysql 执行普通sql语句 redis 执行普通命令
  3. 失败取消:mysql 用rollback进行回滚  redis 用discard 取消本次事务执行
  4. 提交确认:mysql用commit 提交本次事务 redis 用exec

redis事务执行过程:

执行multi之后

redis把后续的命令放入一个队列,

  1. 如果命令语法错误(不是执行错误),则本次事务无法exec提交,可以用discard取消比如:
    1
    2
    3
    4
    5
    6
    7
    
    127.0.0.1:6379> flushdb  OK 
    127.0.0.1:6379> mset a 100 b 200 c 300  OK 
    127.0.0.1:6379> multi  OK
    127.0.0.1:6379> dcerby a 50
    (error) ERR unknown command 'dcerby'
    127.0.0.1:6379> decr a 50
    (error) ERR wrong number of arguments for 'decr' command
  2. 如果语法都正确,最后执行exec后,有命令执行错误,则会跳过错误,继续执行,此时执行discard依然无法撤销正确命令的影响比如:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    
    127.0.0.1:6379> mget a b c
    1) "100"
    2) "200"
    3) "300"
    127.0.0.1:6379> multi
    OK
    127.0.0.1:6379> decr a
    QUEUED
    127.0.0.1:6379> sadd b 5
    QUEUED
    127.0.0.1:6379> decr c
    QUEUED
    127.0.0.1:6379> exec
    1) (integer) 99
    2) (error) WRONGTYPE Operation against a key holding the wrong kind of value
    3) (integer) 299
    127.0.0.1:6379> discard
    (error) ERR DISCARD without MULTI
    127.0.0.1:6379>

有上面的测试可以发现,redis的事务 中的命令,exec之前并不是真正的执行了,而是放到了一个队列中,最后exec时才执行。

redis简单的事务支持明显不符合正常逻辑。

如,库存有1件商品,此时有两个人(A,B)去购买 测试:

在两个终端分别开启两个事务

终端1

1
2
3
4
5
6
7
8
9
10
11
12
127.0.0.1:6379>
127.0.0.1:6379> set agg 1                                   OK
127.0.0.1:6379> get agg
"1"
127.0.0.1:6379> multi
OK
127.0.0.1:6379> decr agg
QUEUED
此时去了终端2里面执行一个完整的事务,且agg的只变成了0
127.0.0.1:6379> exec
1) (integer) -1
127.0.0.1:6379>

终端2

1
2
3
4
5
6
7
8
9
10
11
12
[root@zhang bin]# ./redis-cli
127.0.0.1:6379> get agg
"1"
127.0.0.1:6379> 此时在终端2执行一个事务
127.0.0.1:6379> multi
OK
127.0.0.1:6379> decr agg
QUEUED
127.0.0.1:6379> exec
1) (integer) 0
现在回到终端1去执行exec
127.0.0.1:6379>

对比可以看出,redis并没有mysql中事务隔离级别

不过好在redis提供了watch(unwatch)  用来监视key的变化

和上面相同的命令,只需要在终端1中multi前面加上watch agg

则不会发生agg值变成负一的情况

watch 可以监控多个值,如果有一个变化,则整个事务执行取消。(exec 执行结果提示nli)

redis中使用的是乐观锁,也就是在最后执行exec的时候才去检查watch的监测的key是否有变化

 

 

未经允许不得转载:开心乐窝-乐在其中 » redis 事务

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏