Redis(3)---Redis事务

2年前 (2022) 程序员胖胖胖虎阿
142 0 0

Redis事务

Redis 通过 MULTIEXECDISCARD  和 WATCH 四个命令来实现事务功能。

        MULTI :标记一个事务块的开始。

         EXEC: 执行所有事务块内的命令。

 DISCARD :取消事务,放弃执行事务块内的所有命令。

WATCH key [key ...] :监视一个(或多个) key ,如果在事务执行之前这个(或这些) key 被其他命令所改动,那么事务将被打断。

 

一、事务

   1、是什么?

     可以一次执行多个命令,本质是一组命令的集合。一个事务中的所有命令都会序列化,不许加塞!

   2、能干什么?

     一个队列中,一次性的、顺序性的、排他性的执行一系列的命令。要么一起成功,要么一起失败。排好队,一次性的执行多个redis的命令!

   3、怎么玩?

   通过MULTI指令开启,之后输入多个命令!Redis将它们加入到队列当中,所有的命令通过EXEC来开启执行!通过DISCARD来放弃本次的批处理操作!

 (1)正常执行(好比购物先加入购物车,最后EXEC统一结账。)

192.168.1.66:6379> MULTI    --开启事务
OK
192.168.1.66:6379> set k1 v1
QUEUED
192.168.1.66:6379> set k2 v2
QUEUED
192.168.1.66:6379> set k3 v3
QUEUED
192.168.1.66:6379> set k4 v4
QUEUED
192.168.1.66:6379> get k2
QUEUED
192.168.1.66:6379> EXEC  --结束事务
1) OK
2) OK
3) OK
4) OK
5) "v2"

  (2)DISCARD 撤销所有操作!

192.168.1.66:6379> MULTI
OK
192.168.1.66:6379> set k1 11
QUEUED
192.168.1.66:6379> set k2 22
QUEUED
192.168.1.66:6379> set k3 33
QUEUED
192.168.1.66:6379> DISCARD
OK
192.168.1.66:6379> get k1  --这里的k1的value值还是上面的值,而不是新设置的value值
"v1"    

  (3)加入队列时不出错,下面的都将正常运行,执行时出错不影响其他语句!

192.168.1.66:6379> set k1 v1
OK
192.168.1.66:6379> set k2 v2
OK
192.168.1.66:6379> MULTI
OK
192.168.1.66:6379> incr k1
QUEUED
192.168.1.66:6379> set k2 22
QUEUED
192.168.1.66:6379> EXEC
1) (error) ERR value is not an integer or out of range --在运行是才发现k1不是数字,报错
2) OK     --执行成功

注意:
   (1)当遇到执行错误时,redis放过这种错误,保证事务执行完成。(所以说redis的事务并不是保证原子性
   (2)与mysql中事务不同,在redis事务遇到执行错误的时候,不会进行回滚,而是简单的放过了,并保证其他的命令正常执行。这个区别在实现业务的时候,需要自己保证逻辑符合预期。
   (3)当事务的执行过程中,如果redis意外的挂了。很遗憾只有部分命令执行了,后面的也就被丢弃了。当然如果我们使用的append-only file方式持久化,redis会用单个write操作写入整个事务内容。即是是这种方式还是有可能只部分写入了事务到磁盘。发生部分写入事务的情况 下,redis重启时会检测到这种情况,然后失败退出。可以使用redis-check-aof工具进行修复,修复会删除部分写入的事务内容。修复完后就 能够重新启动了。

 

二、WATCH

       WATCH 命令可以为 Redis 事务提供 check-and-set (CAS)行为。

       被 WATCH 的键会被监视,并会发觉这些键是否被改动过了。 如果有至少一个被监视的键在 EXEC 执行之前被修改了, 那么整个事务都会被取消, EXEC 返回空多条批量回复(null multi-bulk reply)来表示事务已经失败。

1、首先我们不加WATCH进行事务处理

时间

客户端 A

客户端 B

说明

T1

SET name aa

SET age  10

GET name

aa

GET age

10

数据库中两客户端登录,及键初始值。

它们是同步的。

T2

MULTI

SET name bb

Incr age

 

此时,客户端1开启事务,并提交队列命令:

1.想要将当前age自增+1运算;

2.将name值改为bb

T3

 

SET name cc

Incr age

此时,客户端2修改了age值

同时修改name值为cc

T4

EXEC

 

 

T5

GET name

bb

GET age

12

此时,客户端1执行队列命令,发现运算之后age不是理想中的11,而是12原因是被其它客户插足抢先给修改了。name值确实是没有被其它所改变。这样可能导致数据不一致性。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

2、添加WARCH

客户端1-引入“乐观锁”机制 客户端2 说明
 SET age
"10"
 SET name
"zhangsan"

 GET age
"10"
 GET name
"zhangsan"
数据库中两客户端登录,及键初始值。
 WATCH    age name
OK
 MUTLI
OK
 incr age
QUEUED
 set name lisi
QUEUED
  此时,客户端1用watch命令监视age和name,然后开启事务,并提交队列命令
   incr age
(integer) 11
此时,客户端2修改了age值
 exec
(nil)
 get age
"11"
 get name
"zhangsan"
  此时,客户端1执行队列命令,由watch监控发现此期间age的值已经被修改过,则让事整个务回滚,不做任何动作。

watch可以同时监控多个键,在监控期间只要有一个键被其它客户端改变,则整个事务回滚。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

想太多,做太少,中间的落差就是烦恼。想没有烦恼,要么别想,要么多做。少校【1】

 

版权声明:程序员胖胖胖虎阿 发表于 2022年11月23日 上午12:00。
转载请注明:Redis(3)---Redis事务 | 胖虎的工具箱-编程导航

相关文章

暂无评论

暂无评论...