美文网首页
01给女朋友讲讲Redis-事务

01给女朋友讲讲Redis-事务

作者: XueFengDong | 来源:发表于2021-07-02 13:12 被阅读0次

    一、Redis事务的本质

    一组命令的集合,一个事务中的所有命令都会被序列化,在事务执行过程中,会按照顺序执行。

    ------头部 -> set -> set -> set -> 尾部------
    

    特性:

    • 一次性
    • 顺序性
    • 排他性

    Redis事务没有隔离级别的概念。
    Redis单条指令是保证原子性的,但是事务不保证原子性。

    二、Redis事务实践

    主要命令如下:

    • MULTI ->开启事务
    • EXEC ->执行事务
    • DISCARD ->放弃事务

    执行效果如下所示
    1.正常执行事务

    127.0.0.1:6379> MULTI #开启事务
    OK
    127.0.0.1:6379> set k1 v1
    QUEUED
    127.0.0.1:6379> set k2 v2
    QUEUED
    127.0.0.1:6379> get k1
    QUEUED
    127.0.0.1:6379> get k2
    QUEUED
    127.0.0.1:6379> EXEC #执行事务
    1) OK
    2) OK
    3) "v1"
    4) "v2"
    127.0.0.1:6379>
    

    2.放弃当前事务

    127.0.0.1:6379> MULTI #开启事务
    OK
    127.0.0.1:6379> set k1 v1
    QUEUED
    127.0.0.1:6379> set k2 v2
    QUEUED
    127.0.0.1:6379> DISCARD #放弃事务
    OK
    127.0.0.1:6379> get k1 #事务已经被放弃,不会取到值
    (nil)
    127.0.0.1:6379> get k2
    (nil)
    

    3.编译时发生错误
    当事务开启之后,多条命令中包含一条不存在的命令,本次事务会全部放弃。

    127.0.0.1:6379> MULTI #开启事务
    OK
    127.0.0.1:6379> set k1 v1
    QUEUED
    127.0.0.1:6379> setget k2 v2 #此处故意输入错误命令,编译时已经报错
    (error) ERR unknown command `setget`, with args beginning with: `k2`, `v2`, 
    127.0.0.1:6379> EXEC #执行事务,事务全部放弃,不会成功
    (error) EXECABORT Transaction discarded because of previous errors.
    127.0.0.1:6379> get k1 #没有取到编译错误之前设置的值
    (nil)
    

    4.执行时发生错误
    当事务开启之后,某些命令执行了不合理的操作,那么该命令不会生效,但不影响本次事务中其他命令的执行。

    127.0.0.1:6379> set k1 wuhan
    OK
    127.0.0.1:6379> get k1
    "wuhan"
    127.0.0.1:6379> MULTI
    OK
    127.0.0.1:6379> set k2 shanghai
    QUEUED
    127.0.0.1:6379> INCR k1
    QUEUED
    127.0.0.1:6379> set k3 beijing
    QUEUED
    127.0.0.1:6379> EXEC
    1) OK
    2) (error) ERR value is not an integer or out of range #此处k1不是数字,执行incr会报错
    3) OK
    127.0.0.1:6379> get k1
    "wuhan"
    127.0.0.1:6379> get k2 #虽然执行命令INCR k1时出错,没有影响其余正常命令的执行
    "shanghai"
    127.0.0.1:6379> get k3
    "beijing"
    
    

    三、Redis实现乐观锁

    乐观锁

    • 做事很乐观,认为什么时候都不会出问题,所以不会真正上锁。在更新数据的时候去判断一下,在此期间内是否有人修改过数据。
    • 获取version
    • 更新的时候比较version
      Redis中如何实现?
    WATCH key [key ...]
    

    在操作之前监视指定的key,如果事务执行期间被别的线程修改过,那么整个事务将会失效。
    线程1:

    127.0.0.1:6379> set money 1000 #假设账户有1000元
    OK
    127.0.0.1:6379> WATCH money #取之前先监视key
    OK
    127.0.0.1:6379> MULTI #开启事务
    OK
    127.0.0.1:6379(TX)> DECRBY money 500 #取500
    QUEUED
    127.0.0.1:6379(TX)> EXEC #执行事务,返回结果为(nil),代表事务执行失败
    (nil)
    127.0.0.1:6379> get money #查看金额已经发生变动
    "600"
    

    线程2:

    127.0.0.1:6379> get money #账户起始金额为1000
    "1000"
    127.0.0.1:6379> DECRBY money 400 #取400,余额为600
    (integer) 600
    

    相关文章

      网友评论

          本文标题:01给女朋友讲讲Redis-事务

          本文链接:https://www.haomeiwen.com/subject/owstyltx.html