登录
首页 >  Golang >  Go问答

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

来源:stackoverflow

时间:2024-02-21 16:36:28 453浏览 收藏

小伙伴们对Golang编程感兴趣吗?是否正在学习相关知识点?如果是,那么本文《在go-redis中如何在客户端运行非事务管道。Watch函数》,就很适合你,本篇文章讲解的知识点主要包括。在之后的文章中也会多多分享相关知识点,希望对大家的知识积累有所帮助!

问题内容

我有一个类似于以下的场景:

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 

这是我在 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 行位于不同的端口

以上就是本文的全部内容了,是否有顺利帮助你解决问题?若是能给你带来学习上的帮助,请大家多多支持golang学习网!更多关于Golang的相关知识,也可关注golang学习网公众号。

声明:本文转载于:stackoverflow 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>