事务

  • 概述

  • 错误处理

  • WATCH命令

概述

Redis事务是指将多条命令加入队列,一次批量执行多条命令,每条命令会按顺序执行,事务执行过程中不会受客户端传入的命令请求影响。

事务同命令一样都是Redis的最小执行单位,要么全执行,要么全不执行。

Redis事务的相关命令如下:

| MULTI | 标识一个事务的开启 |

|---------|------------|

| EXEC | 执行事务中的所有命令 |

| DISCARD | 放弃事务 |

| WATCH | 监视Key改变 |

| UNWATCH | 放弃监视 |

张三给李四转账500,两个终端,一个演示事务,一个查询余额


[root@localhost ~]# redis-cli -p 6377

127.0.0.1:6377> set user_zs_mount 1000

OK

127.0.0.1:6377> set user_ls_mount 10000

OK

127.0.0.1:6377> MULTI

OK

127.0.0.1:6377(TX)> DECRBY user_zs_mount 500

QUEUED

127.0.0.1:6377(TX)> INCRBY user_ls_mount 500

QUEUED

127.0.0.1:6377(TX)> EXEC



1) (integer) 500

2) (integer) 10500

   127.0.0.1:6377> 


[root@localhost ~]# redis-cli -p 6377



# 未EXEC执行事务之前查询

127.0.0.1:6377> get user_zs_mount    

> 1000

127.0.0.1:6377> get user_ls_mount    

> 10000



# EXEC执行了事务之后查询

127.0.0.1:6377> get user_zs_mount    

> 500                                 

127.0.0.1:6377> get user_ls_mount    

> 10500                               

当事务开启时,事务期间的命令并没有立即执行,而是加入队列,只有执行EXEC命令时,事务中的命令才会按照顺序依次执行,从而事务间就不会导致数据脏读、不可重复读、幻读的问题,也就没有隔离级别。

错误处理

  • 语法错误:

127.0.0.1:6377> MULTI

OK

127.0.0.1:6377(TX)> INCRBY user_zs_mount 500

QUEUED

127.0.0.1:6377(TX)> DECRBY user_ls_mount

(error) ERR wrong number of arguments for 'decrby' command

127.0.0.1:6377(TX)> EXEC                                           

(error) EXECABORT Transaction discarded because of previous errors.

127.0.0.1:6377> get user_zs_mount                                  

> 500

127.0.0.1:6377> get user_ls_mount                                  

> 10500

事务中只要有一个命令有语法错误,执行EXEC命令后Redis就会直接返回错误,正确的命令也不会执行。

  • 运行错误:

127.0.0.1:6377> MULTI

OK

127.0.0.1:6377(TX)> INCRBY user_zs_mount 500

QUEUED

127.0.0.1:6377(TX)> DECRBY user_ls_mount aa

QUEUED

127.0.0.1:6377(TX)> EXEC

  1) (integer) 1000

  2) (error) ERR value is not an integer or out of range



127.0.0.1:6377> get user_zs_mount

   > 1000

127.0.0.1:6377> get user_ls_mount

   > 10500

运行错误是在命令执行时才出现的错误,这种错误在实际执行之前Redis无法发现,如果事务中出现了运行错误,事务里其它的命令依然会继续执行,包括出错之后的命令。

Redis的事务不支持回滚

Redis官网解释:

  • 语法错误是编程导致的错误,应该在开发过程中解决

  • 不用支持回滚功能,Redis内部简单化,而且还比较快

  • 在事务命令入队过程中,发现相关命令逻辑使用错误,可以进行放弃该事务

  • 如果使用错误的Redis命令,且没有放弃事务,最终也会导致事务整体执行失败

WATCH命令

WATCH通过监视指定Redis Key,一旦其中一个值发生改变(被修改或删除),之后的事务就不会执行。


127.0.0.1:6377> get user_ls_mount

> 10500> 

127.0.0.1:6377> WATCH user_ls_mount

OK

127.0.0.1:6377> INCRBY user_ls_mount 50

(integer) 10550

127.0.0.1:6377> MULTI

OK

127.0.0.1:6377(TX)> INCRBY user_ls_mount 500

QUEUED

127.0.0.1:6377(TX)> EXEC

(nil)

127.0.0.1:6377> get user_ls_mount

> 10550 

WATCH取消监视:

  • 事务执行之后,不管是否执行成功还好是失败,都会取消对应的监视

  • 当监视的客户端断开连接时

  • UNWATCH命令取消所有Key的监视