美文网首页
Redis事务

Redis事务

作者: NotFoundW | 来源:发表于2020-04-22 10:07 被阅读0次

    1. MULTI标记事务开始,事务块内的多条命令会按照先后顺序被放进一个队列当中。而EXEC则用于执行事务块内所有的命令。

    Command

    $ redis-cli.exe -h 127.0.0.1 -p 6379
    127.0.0.1:6379> set dog 1
    OK
    127.0.0.1:6379> MULTI
    OK
    127.0.0.1:6379> INCR dog
    QUEUED
    127.0.0.1:6379> INCR dog
    QUEUED
    127.0.0.1:6379> EXEC
    1) (integer) 2
    2) (integer) 3
    

    Code

    pool.FactoryPool()是自己的连接池工厂函数,此处不特别记录。

    func MultiAndExec() {
        c := pool.FactoryPool()
        defer c.Close()
        defer c.Do("DEL", "dog")
        c.Do("SET", "dog", 1)
        res, _ := c.Do("MULTI")
        fmt.Println("Result of MULTI:", res)
        //  Add commands into queue.
        res, _ = c.Do("INCR", "dog")
        fmt.Println("Result of adding command:", res)
        res, _ = c.Do("INCR", "dog")
        fmt.Println("Result of adding command:", res)
        //  Execute all the commands in transaction.
        results, _ := redis.Ints(c.Do("EXEC"))
        for _, v := range results {
            fmt.Println(v)
        }
    }
    

    Output

    $ go run main.go
    Result of MULTI: OK
    Result of adding command: QUEUED
    Result of adding command: QUEUED
    2
    3
    

    2. DISCARD用于取消事务,即放弃执行事务内的所有命令。

    可以看到,当使用DISCARD取消事务后,EXEC返回错误。

    Command

    $ redis-cli -h 127.0.0.1 -p 6379
    127.0.0.1:6379> MULTI
    OK
    127.0.0.1:6379> incr dog
    QUEUED
    127.0.0.1:6379> DISCARD
    OK
    127.0.0.1:6379> EXEC
    (error) ERR EXEC without MULTI
    

    Code

    func Discard() {
        c := pool.FactoryPool()
        defer c.Close()
        defer c.Do("DEL", "dog")
        c.Do("SET", "dog", 1)
        res, _ := c.Do("MULTI")
        fmt.Println("Result of MULTI:", res)
        //  Add commands into queue.
        res, _ = c.Do("INCR", "dog")
        fmt.Println("Result of adding command:", res)
        //  Cancel the transaction.
        res, _ = c.Do("DISCARD")
        fmt.Println("Result of DISCARD:", res)
        //  Execute all the commands in transaction, will return nil.
        resAfterDis, err := c.Do("EXEC")
        if err != nil {
            colorlog.Error(err.Error())
        }
        fmt.Println(resAfterDis)
    }
    

    Output

    $ go run main.go 
    Result of MULTI: OK
    Result of adding command: QUEUED
    Result of DISCARD: OK
    [ERR]2020/04/21 22:45:40 ERR EXEC without MULTI
    ERR EXEC without MULTI
    

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

    Command

    • 在第一个终端监视"dog",并标记事务开始,添加命令到队列
    $ redis-cli.exe -h 127.0.0.1 -p 6379
    127.0.0.1:6379> WATCH dog
    OK
    127.0.0.1:6379> MULTI
    OK
    127.0.0.1:6379> incr dog
    QUEUED
    127.0.0.1:6379> incr dog
    QUEUED
    
    • 在第二个终端改变"dog"的值,用于打断事务
    $ redis-cli -h 127.0.0.1 -p 6379
    127.0.0.1:6379> set dog 10
    OK
    
    • 再在第一个终端执行EXEC。事务已被打断,EXEC返回nil
    127.0.0.1:6379> EXEC
    (nil)
    

    Code

    func Watch() {
        c1 := pool.FactoryPool()
        c2 := pool.FactoryPool()
        defer c1.Close()
        defer c2.Close()
        defer c1.Do("DEL", "dog")
        c1.Do("SET", "dog", 1)
        watchRes, _ := c1.Do("WATCH", "dog")
        fmt.Println("Result of watch is:", watchRes)
        res, _ := c1.Do("MULTI")
        fmt.Println("Result of MULTI:", res)
        //  Add commands into queue.
        res, _ = c1.Do("INCR", "dog")
        fmt.Println("Result of adding command:", res)
        res, _ = c1.Do("INCR", "dog")
        fmt.Println("Result of adding command:", res)
        //  Set dog's value in second connection.
        c2.Do("SET", "dog", 10)
        //  Execute all the commands in transaction in first connection.
        resAfterWatchAndSet, _ := c1.Do("EXEC")
        fmt.Println("After WATCH and SET, result of EXEC is:", resAfterWatchAndSet)
    }
    

    4. UNWATCH用于取消WATCH命令对所有key的监视。但是据观察,貌似必须跟WATCH命令在同一个连接里,才能起到效果?

    Command

    • 在第一个终端里开始WATCH
    $ redis-cli.exe -h 127.0.0.1 -p 6379
    127.0.0.1:6379> watch dog
    OK
    
    • 在第二个终端里标记事务但不执行
    $ redis-cli -h 127.0.0.1 -p 6379
    127.0.0.1:6379> multi
    OK
    127.0.0.1:6379> incr dog
    QUEUED
    127.0.0.1:6379> incr dog
    QUEUED
    
    • 在第一个终端里取消监视,并改变"dog"的值
    127.0.0.1:6379> unwatch
    OK
    127.0.0.1:6379> set dog 33
    OK
    
    • 在第二个终端里执行事务。可以看到事务正常执行,因为修改"dog"的值之前,已经取消监视
    127.0.0.1:6379> exec
    1) (integer) 34
    2) (integer) 35
    

    Code

    func Unwatch() {
        c1 := pool.FactoryPool()
        c2 := pool.FactoryPool()
        defer c1.Close()
        defer c2.Close()
        defer c1.Do("DEL", "dog")
        c1.Do("SET", "dog", 1)
        watchRes, _ := c1.Do("WATCH", "dog")
        fmt.Println("Result of watch is:", watchRes)
        res, _ := c2.Do("MULTI")
        fmt.Println("Result of MULTI:", res)
        //  Add commands into queue.
        res, _ = c2.Do("INCR", "dog")
        fmt.Println("Result of adding command:", res)
        res, _ = c2.Do("INCR", "dog")
        fmt.Println("Result of adding command:", res)
        //  Unwatch, and then set dog's value.
        unwatchRes, _ := c1.Do("UNWATCH")
        fmt.Println("Result of unwatch is:", unwatchRes)
        c1.Do("SET", "dog", 33)
        //  Execute all the commands in transaction in first connection.
        resAfterUnwatchAndSet, _ := redis.Ints(c2.Do("EXEC"))
        for _, v := range resAfterUnwatchAndSet {
            fmt.Println(v)
        }
    }
    

    Output

    $ go run main.go 
    Result of watch is: OK
    Result of MULTI: OK
    Result of adding command: QUEUED
    Result of adding command: QUEUED
    Result of unwatch is: OK
    34
    35
    

    相关文章

      网友评论

          本文标题:Redis事务

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