美文网首页
Redis学习笔记(2)

Redis学习笔记(2)

作者: SYFHEHE | 来源:发表于2020-11-29 17:25 被阅读0次

    1. 事务

    1.1 Redis事务的概念

    Redis 事务的本质是一组命令的集合。事务支持一次执行多个命令,一个事务中所有命令都会被序列化。在事务执行过程,会按照顺序串行化执行队列中的命令,其他客户端提交的命令请求不会插入到事务执行命令序列中。
      总结说:redis事务就是一次性、顺序性、排他性的执行一个队列中的一系列命令。

    • Redis事务没有隔离级别的概念:
      批量操作在发送 EXEC 命令前被放入队列缓存,并不会被实际执行,也就不存在事务内的查询要看到事务里的更新,事务外查询不能看到。
    • Redis不保证原子性:
      单个 Redis 命令的执行是原子性的,但 Redis 没有在事务上增加任何维持原子性的机制,所以 Redis 事务的执行并不是原子性的。. 事务可以理解为一个打包的批量执行脚本,但批量指令并非原子化的操作,中间某条指令的失败不会导致前面已做指令的回滚,也不会造成后续的指令不做。

    1.2 Redis事务的三个阶段:

    1. 开始事务
    2. 命令入队
    3. 执行事务

    1.3 Redis事务相关命令:

    watch key1 key2 ... :监视一或多个key,如果在事务执行之前,被监视的key被其他命令改动,则事务被打断 ( 类似乐观锁 )

    multi :标记一个事务块的开始( queued )

    exec :执行所有事务块的命令 ( 一旦执行exec后,之前加的监控锁都会被取消掉 )

    discard :取消事务,放弃事务块中的所有命令

    unwatch :取消watch对所有key的监控

    1.4 Redis事务使用案例:

    案例一: exec

    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> set k3 v3
    QUEUED
    127.0.0.1:6379> exec
    1) OK
    2) OK
    3) OK
    127.0.0.1:6379>
    

    案例二: discard

    127.0.0.1:6379> get k1
    "v1"
    127.0.0.1:6379> multi
    OK
    127.0.0.1:6379> set k4 v4
    QUEUED
    127.0.0.1:6379> discard
    OK
    127.0.0.1:6379> get k4
    (nil)
    127.0.0.1:6379>
    

    案例三: 编译型异常

    编译型异常时候,事务中所有的命令都不会被执行

    127.0.0.1:6379> multi
    OK
    127.0.0.1:6379> getset k3
    (error) ERR wrong number of arguments for 'getset' command
    127.0.0.1:6379> set k4 v4
    QUEUED
    127.0.0.1:6379> exec
    (error) EXECABORT Transaction discarded because of previous errors.
    

    案例四: 运行时异常
    运行异常的时候,有错误的命令不运行,其他命令会运行。

    127.0.0.1:6379> multi
    OK
    127.0.0.1:6379> incr k1
    QUEUED
    127.0.0.1:6379> set k6 v6
    QUEUED
    127.0.0.1:6379> set k7 v7
    QUEUED
    127.0.0.1:6379> exec
    1) (error) ERR value is not an integer or out of range
    2) OK
    3) OK
    127.0.0.1:6379>
    

    案例五: 监控

    • 悲观锁:无论做什么都加锁
    • 乐观锁:什么都不加锁。大多数是基于数据版本(version)的记录机制实现的。即为数据增加一个版本标识,在基于数据库表的版本解决方案中,一般是通过为数据库表增加一个”version”字段来实现读取出数据时,将此版本号一同读出,之后更新时,对此版本号加1。此时,将提交数据的版本号与数据库表对应记录的当前版本号进行比对,如果提交的数据版本号大于数据库当前版本号,则予以更新,否则认为是过期数据。redis中可以使用watch命令会监视给定的key,当exec时候如果监视的key从调用watch后发生过变化,则整个事务会失败。也可以调用watch多次监视多个key。这样就可以对指定的key加乐观锁了。注意watch的key是对整个连接有效的,事务也一样。如果连接断开,监视和事务都会被自动清除。当然了exec,discard,unwatch命令都会清除连接中的所有监视。

    情况1:正常执行

    127.0.0.1:6379> set money 300
    OK
    127.0.0.1:6379> set out 0
    OK
    127.0.0.1:6379> keys *
    1) "money"
    2) "out"
    127.0.0.1:6379> watch money
    OK
    127.0.0.1:6379> DECRBY money 20
    (integer) 280
    127.0.0.1:6379> incrby out 20
    (integer) 20
    127.0.0.1:6379>
    

    情况二:两个客户端
    客户端1:

    127.0.0.1:6379> watch money #监控money
    OK
    127.0.0.1:6379> multi
    OK
    127.0.0.1:6379> DECRBY money 20
    QUEUED
    127.0.0.1:6379> incrby out 20
    QUEUED 
    
    #在这段时间,另外一个线程修改了money的值。
    
    127.0.0.1:6379> exec
    (nil)
    
    #提交失败
    

    客户端2:

    127.0.0.1:6379> get money
    "280"
    127.0.0.1:6379> set money 400
    OK
    127.0.0.1:6379>
    

    相关文章

      网友评论

          本文标题:Redis学习笔记(2)

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