Redis 笔记(四)事物

事务:把一组数据库命令放在一起执行,保证操作原子性,要么同时成功,要么同时失败。

Redis的事务:允许把一组 Redis 命令放在一起,把命令进行序列化,然后一起执行保证部分原子性

  • 原子性:数据库中的某个事务A中要更新t1表、t2表的某条记录,当事务提交,t1、t2两个表都被更新,若其中一个表操作失败,事务将回滚。
  • 非原子性:数据库中的某个事务A中要更新t1表、t2表的某条记录,当事务提交,t1、t2两个表都被更新,若其中一个表操作失败,另一个表操作继续,事务不会回滚。(当然对于关系型数据库不会出现非原子性)
  • MULTI :开启事务,redis会将后续的命令逐个放入队列中,然后使用EXEC命令来原子化执行这个命令系列。
  • EXEC:执行事务中的所有操作命令。必须与MULTI命令成对使用
  • DISCARD:取消事务,放弃执行事务块中的所有命令。
  • WATCH:监视一个或多个key,如果事务在执行前,这个key(或多个key)被其他命令修改,则事务被中断,不会执行事务中的任何命令。
  • UNWATCH:取消WATCH对所有key的监视。

---------------------------------------------------------------------------------------------------------------------------------举例

(1) 给k1、k2分别赋值,在事务中修改k1、k2,执行事务后,查看k1、k2值都被修改。

127.0.0.1:6379> multi

OK

127.0.0.1:6379(TX)> set k1 v1

QUEUED

127.0.0.1:6379(TX)> set k2 v2

QUEUED

127.0.0.1:6379(TX)> exec

1) OK

2) OK

127.0.0.1:6379>

(2)语法错误(编译器错误),在开启事务后,修改k1值为11,k2值为22,但k2语法错误,最终导致事务提交失败,k1、k2保留原值。

127.0.0.1:6379> keys *

1) "k2"

2) "k1"

127.0.0.1:6379> multi

OK

127.0.0.1:6379(TX)> set k1 11

QUEUED

127.0.0.1:6379(TX)> seta k2 22

(error) ERR unknown command 'seta', with args beginning with: 'k2' '22'

127.0.0.1:6379(TX)> exec

(error) EXECABORT Transaction discarded because of previous errors.

127.0.0.1:6379>

(3)类型错误(运行时错误),在开启事务后,修改k1值为11,k2值加1,在运行时检测类型错误,最终导致事务提交失败,此时事务并没有回滚,而是跳过错误命令继续执行, 结果k1值改变、k2保留原值。

127.0.0.1:6379> keys *

1) "k2"

2) "k1"

127.0.0.1:6379> multi

OK

127.0.0.1:6379(TX)> set k1 11

QUEUED

127.0.0.1:6379(TX)> incr k2

QUEUED

127.0.0.1:6379(TX)> exec

1) OK

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

127.0.0.1:6379> keys *

1) "k2"

2) "k1"

127.0.0.1:6379> get k1

"11"

127.0.0.1:6379> get k2

"v2"

127.0.0.1:6379>

以上两个例子总结出,多数事务失败是由语法错误或者数据结构类型错误导致的,语法错误说明在命令入队前就进行检测的,而类型错误是在执行时检测的,Redis为提升性能而采用这种简单的事务,这是不同于关系型数据库的,特别要注意区分。 

(4)取消事物

127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> set k1 33
QUEUED
127.0.0.1:6379> set k2 34
QUEUED
127.0.0.1:6379> DISCARD
OK

(5)WATCH监视 key

严格的说Redis的命令是原子性的,而事务是非原子性的,我们要让Redis事务完全具有事务回滚的能力,需要借助于命令WATCH来实现。

Redis使用WATCH命令来决定事务是继续执行还是回滚,那就需要在MULTI之前使用WATCH来监控某些键值对,然后使用MULTI命令来开启事务,执行对数据结构操作的各种命令,此时这些命令入队列。

当使用EXEC执行事务时,首先会比对WATCH所监控的键值对,如果没发生改变,它会执行事务队列中的命令,提交事务;如果发生变化,将不会执行事务中的任何命令,同时事务回滚。当然无论是否回滚,Redis都会取消执行事务前的WATCH命令。

             

Redis执行事务过程

设置三个变量,version(版本)、balance1(金额)、balance2(金额2),在事务开始前用WATCH监控 version,每次修改金额的同时修改 version。这个时候在起另一个控制窗口,修改version,回到主窗口执行事物操作,结果失败。

127.0.0.1:6379> keys *

1) "balance2"

2) "balance1"

3) "version"

127.0.0.1:6379> watch version

OK

127.0.0.1:6379> multi

OK

127.0.0.1:6379(TX)> decrby balance1 50

QUEUED

127.0.0.1:6379(TX)> incrby balance2 50

QUEUED

127.0.0.1:6379(TX)> exec

1) (integer) 450

2) (integer) 1050

127.0.0.1:6379>

-------------------------------------------------------------------------------------------------------------------------

 

 (5)UNWATCH取消监视所有 key

127.0.0.1:6379> watch version

OK

127.0.0.1:6379> unwatch

OK

127.0.0.1:6379>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值