美文网首页
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系列(十):事务

    redis有事务么? redis官方说是有事务的。但这个事务不是我们普遍理解的mysql事务。 redis的事务不...

  • 九、Redis 事务

    Redis 事务 Redis事务描述: Redis事务允许在单个步骤中执行一组命令。以下是Redis事务的两个属性...

  • Redis事务

    redis事务机制 Redis事务与传统关系型事务的比较

  • Redis事务

    转载自Redis之Redis事务 Redis事务的概念: Redis 事务的本质是一组命令的集合。事务支持一次执行...

  • redis中的事物、消息订阅、持久化

    Redis 中的事务 Redis支持简单的事务 Redis与 mysql事务的对比 注: rollback与dis...

  • Redis简单操作记录

    Redis事务 1.Redis事务本质:一组命令的集合,加入队列,然后执行,执行完事务结束。 redis事务: ①...

  • JavaGuide知识点整理——Redis面试题总结(下)

    Redis事务 如何使用Redis事务? Redis可以通过multi,exec,discard和watch等命令...

  • redis 常用指令

    Redis 的事务 Redis 的事务处理与 RDBMS 的事务有一些不同。首先 Redis 不支持事务的回滚机制...

  • Redis学习笔记:事务

    Redis学习笔记:事务 原文链接:Redis学习笔记:事务 一、事务的描述 和MySQL一样,Redis中也有事...

  • 事务

    简介 MULTI、EXEC、DISCARD、WATCH是redis事务的基础。事务特征如下: redis事务允许将...

网友评论

      本文标题:Redis事务

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