首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在go-redis中从client.Watch函数运行非事务管道

如何在go-redis中从client.Watch函数运行非事务管道
EN

Stack Overflow用户
提问于 2020-01-09 22:20:41
回答 1查看 2.5K关注 0票数 1

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

代码语言:javascript
复制
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似乎都返回了一个多/exec实现,这意味着如果我将其用于读取数据(第1阶段),我将失去用于更新数据的第二个管道中的监视保护。

任何解决方案都将付诸实施。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-01-10 11:19:41

您可以使用client.Pipelined(...而不是tx..Pipelined(...来使用管道,但是它将使用go-redis池中的另一个连接(从redis服务器透视图的另一个客户端)发送到redis服务器。不过,我不认为这是个问题。

go-redis事务使用粘性连接来确保从同一连接发送整个事务(从WATCH开始)。内部tx.baseClient未导出。无法使用相同的连接发送管道。

代码语言:javascript
复制
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程序的输出:

代码语言:javascript
复制
get getPipe: preVal
[get getPipe: preVal set pipe1 p1: OK]
Value read for 'getPipe': preVal
get myKey: insideMulti <nil>

这就是我在redis-cli上看到的MONITOR command

代码语言:javascript
复制
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行位于不同的端口上。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59672948

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档