Redis事务

2020-04-22  本文已影响0人  NotFoundW

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

$ 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
$ redis-cli -h 127.0.0.1 -p 6379
127.0.0.1:6379> set dog 10
OK
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

$ 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
127.0.0.1:6379> unwatch
OK
127.0.0.1:6379> set dog 33
OK
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
上一篇下一篇

猜你喜欢

热点阅读