【Redis高手修炼之路】④ 事务

事务

可以一次执行多个命令,是一个命令组,一个事务中,所有命令都会序列化(排队),不会被插队;一个队列中,一次性,顺序性,排他性的执行一系列命令!

三特性

  • 隔离性:所有命令都会按照顺序执行,事务在执行的过程中,不会被其他客户端送来的命令打断
  • 没有隔离级别:队列中的命令没有提交之前都不会被实际的执行,不存在“事务中查询要看到事务里的更新,事务外查询不能看到”这个头疼的问题
  • 不保证原子性:冤有头债有主,如果一个命令失败,但是别的命令可能会执行成功,没有回滚

三步走

  • 开启 multi
  • 入队queued
  • 执行 exec

与关系型数据库事务相比

  • multi:可以理解成关系型事务中的 begin
  • exec :可以理解成关系型事务中的 commit
  • discard :可以理解成关系型事务中的 rollback

同生共死

同生: 开启事务,加入队列,一起执行,一起成功!

127.0.0.1:6379> multi      # 开启事务
OK
127.0.0.1:6379> set k1 1   # 加入队列
QUEUED
127.0.0.1:6379> set k2 2
QUEUED
127.0.0.1:6379> set k3 3
QUEUED
127.0.0.1:6379> get k2
QUEUED
127.0.0.1:6379> exec       # 执行,全部成功
1) OK
2) OK
3) OK
4) "2"

共死: 放弃之前的操作,不执行加入队列的命令!

127.0.0.1:6379> multi      				    # 开启事务
OK
127.0.0.1:6379> set k1 a					# 修改数据k1的值
QUEUED										# 加入队列
127.0.0.1:6379> get k1
QUEUED
127.0.0.1:6379> discard						# 放弃操作
OK
127.0.0.1:6379> get k1						# 数据没有修改,还是1 
"1"

一只老鼠坏了一锅汤

一句报错,全部取消,恢复到原来的值

127.0.0.1:6379> multi				 # 开启事务
OK
127.0.0.1:6379> set name tom		# 加入队列
QUEUED
127.0.0.1:6379> sett age 12			# 错误的命令,报错
(error) ERR unknown command `sett`, with args beginning with: `age`, `12`, 
127.0.0.1:6379> set gender boy     # 加入队列
QUEUED
127.0.0.1:6379> exec			    # 执行
(error) EXECABORT Transaction discarded because of previous errors.
127.0.0.1:6379> get name           # 查看数据为空
(nil)
127.0.0.1:6379> get gender		   # 查看数据为空
(nil)

冤有头债有主

追究责任,谁的错,找谁去

127.0.0.1:6379> keys *
1) "k1"
2) "key"
3) "k2"
4) "k3"
127.0.0.1:6379> get key
"v1"
127.0.0.1:6379> multi				# 开启事务
OK
127.0.0.1:6379> incr key			# key的值+1,虽然v1不能+1
QUEUED
127.0.0.1:6379> set k3 3			# 加入队列
QUEUED
127.0.0.1:6379> exec				# 执行
1) (error) ERR value is not an integer or out of range    # 报错
2) OK				# 成功

watch监控

测试:模拟收入与支出

  • 正常情况下:
127.0.0.1:6379> set in 100     	 # 收入100元
OK
127.0.0.1:6379> set out 0		 # 支出0元
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> decrby in 20	 # 收入-20
QUEUED
127.0.0.1:6379> incrby out 20	 # 支出+20
QUEUED
127.0.0.1:6379> exec
1) (integer) 80
2) (integer) 20 				# 结果,没问题!
  • 特殊情况下:
127.0.0.1:6379> watch in 			# 监控收入in
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> decrby in 20
QUEUED
127.0.0.1:6379> incrby out 20
QUEUED
127.0.0.1:6379> exec
(nil) # 在exec之前,我开启了另一个窗口(线程),对监控的in做了修改,所以本次的事务将被打断(失效),类似于“乐观锁”

unwatch:取消watch命令对所有key的操作,一旦执行了exec命令,那么之前加的所有监控自动失效!

猜你喜欢

转载自blog.csdn.net/weixin_52986315/article/details/127501841
今日推荐