go之如何从客户端运行非事务管道。go-redis中的Watch函数

kerrycode 阅读:29 2025-06-02 22:19:02 评论:0

我有一个类似于以下情况:

txf := func(tx *redis.Tx) error { 
  // Phase 1:   
  // read some stuff by several get/hget request which I want to send with pipeline 
  // to avoid unnecessarily rounds to the redis server  
 
  // Phase 2: Prepare new data based on read data 
 
  // Phase 3: Write the new data with a transaction to use the watch protection if original keys changed 
  _, err = tx.Pipelined(func(pipe redis.Pipeliner) error { 
             // pipe handles the error case 
             pipe.Set(key, value, 0) 
             return nil}) 
  return err 
} 
err := client.Watch(txf, key) 

通过读取库代码,在这种情况下,tx.TxPipeline和tx.Pipeline似乎都返回了multi/exec实现,这意味着如果我将其用于读取数据(阶段1),我将在我用来更新数据的第二条管道。
任何解决方案都将适用。

请您参考如下方法:

您可以使用使用client.Pipelined(...而不是tx..Pipelined(...的管道,但是它将使用go-redis池中的另一个连接(从redis服务器角度来看的另一个客户端)将其发送到redis服务器。我认为这不是问题。
go-redis事务使用粘性连接来确保从WATCH开始的整个事务都是从同一连接发送的。内部tx.baseClient未导出。无法使用相同的连接发送管道。

txf := func(tx *redis.Tx) error { 
  // Phase 1:   
  var getPipe *redis.StringCmd 
  cmds, err := client.Pipelined(func(pipe redis.Pipeliner) error { 
        getPipe = pipe.Get("getPipe") 
        pipe.Set("pipe1", "p1", 0) 
        return nil 
  }) 
  fmt.Println(getPipe) 
  fmt.Println(cmds) 
  val, _ := getPipe.Result() 
  fmt.Println("Value read for 'getPipe':", val) 
 
  // Phase 2: Prepare new data based on read data 
 
  // Phase 3 
  _, err = tx.Pipelined(func(pipe redis.Pipeliner) error { 
    // pipe handles the error case 
    pipe.Set(key, value, 0) 
    return nil}) 
  return err 
} 
err := client.Watch(txf, key) 
fmt.Println(client.Get(key), err) 

上面的go程序的输出:
get getPipe: preVal 
[get getPipe: preVal set pipe1 p1: OK] 
Value read for 'getPipe': preVal 
get myKey: insideMulti <nil> 

这就是我在redis-cli上使用 MONITOR command看到的内容:
1 ...1:65506] "watch" "myKey" 
2 ...1:65507] "get" "getPipe" 
3 ...1:65507] "set" "pipe1" "p1" 
4 ...1:65506] "MULTI" 
5 ...1:65506] "set" "myKey" "insideMulti" 
6 ...1:65506] "EXEC" 
7 ...1:65506] "unwatch" 
8 ...1:65506] "get" "myKey" 

注意行2和3在不同的端口上


标签:Redis
声明

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

关注我们

一个IT知识分享的公众号