定义

Redis事务是指把所有redis指令包起来,然后(exec期间)一次性顺序性完成这些reids指令,在整个reids指令执行期间不允许其他其他客户但指令插队

Redis事务特性

打包性:提交的命令集合会当成一个整体去执行

顺序性:执行顺序会按照指令放入包中的顺序执行

隔离性:Redis命令包执行期间,不会被其他客户端指令插队

非原子性:比如Redis指令包中有5条redis执行,其中第二条执行执行失败,第一条执行的指令不会回滚,第二条指令会跳过继续执行后边的指令

Redis事务三阶段

开始事务  -- 不加锁

命令: MUTI

解释:告诉redis服务器,后边redis指令先不执行

效果:MUTI之后输入的指令(排除EXEC, DISCARD,MUTI,WATCH)不会立即执行,而是放入一个Redis队列里

指令入队  --不加锁

命令: 你想要执行的Redis命令,比如set key value, INCR counter等

解释:将你执行的redis指令放入Reids队列里,但不会立即执行这个redis指令集

效果:每输入一条reids指令,Redis会检查这条Redis指令语法。如果没错会返回QUEUED表示你输入的这条redis指令已入队,如果语法错误则,redis会报错并且整个事务都会标记为错误,执行exec后一条指令也不会执行。注意这里只是检查Reids指令的语法而不是逻辑问题

    如下例中,getset k3是语法级别错误而非逻辑错误(比如数据类型),所以执行exec时会将整个包中redis指令都回滚

         

 

事务执行 & 事务取消  -- 加锁

命令: EXEC/DISCARD

解释:

  选项A执行exec时,

         场景1:所以指令都执行成功条件下,Redis会原子性执行指令包里的所有reids指令,执行完成后Reids客户端就退出事务状态  --原子性

    场景2:指令包中存在某一条执行失败条件下,这条失败指令之前的指令不会回滚,跳过当前错误的指令,继续执行后边指令  --非原子性

    如下例中,k1第一次设置为aa这种string类型,在接下来执行incr k1对string类型是不支持的,所以只有第一条执行失败,后边的继续执行不受其影响

                        

                      

    场景3:指令包中某条指令出现语法错误或者Watch监控失败条件下,当输入exec后会返回空,表明指令包中任何指令都没有执行

  选项B执行Discard时,

    命令:discard

    解释:告诉redis刚才用户输入的指令都作废

    效果:redis清空刚刚用户输入redis队列中内容,客户端退出事务

Redis相关命令

MUTI:标记事务块的开始,之后用户输入的指令都会进入事务队列中

EXEC:执行事务队列中reids指令

DISCARD:取消执行事务队列中指令

WATCH:WATCH [k1, k2...]监控一个或多个key,在执行exec前,任何被watch监控的key被其他客户端指令修改了,执行exec时都不会执行事务队列的任何指令,并且返回空表示事务执行失败,这是一种乐观锁(这个Watch key相当于乐观锁里的version)。Watch是非常重要的一个命令,因为redis在命令阶段MUTI之后,EXEC之前是不加锁的,其他客户端是可以修改数据的,如果你的操作里以来某个key就需要监控这个key,确保你在执行事务前这个key没有被其他客户端修改

如下启动两个窗口,先启动窗口1

 再在窗口2中对balance修改

 然后再在窗口1 中执行redis事务操作,由于第一步中启用了watch balance操作,所以这一步操作失败了,返回nil

 

posted on 2025-06-09 14:41  colorfulworld  阅读(13)  评论(0)    收藏  举报