node.js - 如何让 Go 应用程序等待 Redis 列表中的数据可用?

标签 node.js go redis background-process

我有一个使用 Radix Redis client for Go 的 Go 应用程序.它的工作是作为后台进程运行,并等待 Redis 列表将项目添加到其中进行处理。

背景(随意跳过):我有一个 Node.js 网络应用程序,它需要从外部 API 请求数据,而众所周知,这至少需要一整秒或更长时间才能完成回应。数据不是立即需要的,所以我让 Node 应用程序将一个项目添加到 Redis 列表,然后继续处理重要的事情。与此同时,我有一个 Go 应用程序,它应该在后台运行,并在每次发现一个项目被添加到列表中时做一些工作。

现在它只是一个连接到 Redis 的 main 函数,并使用 Redis BRPOP 命令检查列表中是否有项目(因为我希望 Redis在等待作业时阻塞)。运行程序会导致建立连接,然后...

  • 如果列表中有一个项目,Go 应用会根据需要处理它
  • 如果列表中没有项目,Go 应用就会退出

我需要 Go 应用程序只是坐在那里等待新项目,我真的不想求助于轮询,特别是因为 BRPOP 和 BLPUSH 命令是专门制作的,所以应用程序不需要轮询。

我目前的解决方案是创建一个无限循环,永远一遍又一遍地运行 BRPOP 命令。这感觉是错误的做法。

这是到目前为止的整个程序(我是 Go 的新手,但不是编程的新手,所以不要笑得太厉害):

package main

import (
  "fmt"
  "github.com/fzzy/radix/redis"
)

func main() {
  client, err := redis.Dial("tcp", "localhost:6379")

  if err != nil {
    fmt.Println("An error message just for debug purposes")
  } else {
    // Here I check to make sure the server is responding
    ping := client.Cmd("PING")
    fmt.Println(ping) // Just to be sure I'm doing things right

    for {
      fmt.Println("Looking for a new Q item...")
      workItem, err := client.Cmd("BRPOP", "q:test").Str()

      if err != nil {
        fmt.Println("No error, " + workItem)
      }
    }
  }
}

那么让 Go 应用等待 Redis 列表中的数据可用的正确方法是什么?

更新:根据一些评论,我将进一步解释我的期望和正在发生的事情。

我对阻塞 Redis 命令的理解是,它只会暂停调用它的程序,直到它有要返回的内容。所以在我的例子中,当运行程序时队列中没有任何项目,程序打印:

Looking for a new Q item...
No error, 

它无限地打印上面的内容,这是有道理的,因为我有一个永无止境的 for 循环但是因为我使用的是阻塞命令,我希望它的行为更像一个推送。我希望循环只是暂停并等到队列中有一个项目,然后再继续下一次迭代。我担心它即使没有队列项也会继续循环,因为 BRPOP 命令的不断涌现(尽管它是一个阻塞命令),最终该进程将开始不必要地消耗资源并减慢 Redis 的速度.

所以我想现在新的问题是 - 有没有更好的方法让 Go 程序在等待 Redis 列表(或我的临时队列)中的新项目时保持运行? - 以当前形式运行此程序是否会消耗比应有的更多资源和/或降低 Redis 性能?

已解决

感谢@JimB 关于“您忽略的错误...”的问题,我再次查看了代码以确保我没有遗漏一些明显的东西。我是:原来在我的循环中我已经切换了错误和成功处理代码。所以每次出错时,我都会向控制台打印一条成功消息,这样我就可以看到程序内部发生了什么。切换代码并正确处理错误后,我发现调用 BRPOP 时参数太少。我修复了代码,现在循环将一直卡在那里,直到列表中有要处理的内容。

更正以下行:

// We now import "log" now as well
// Inside the for loop...
if err != nil {
  log.Fatal(err) // This alerted me to the wrong # of arguments issue
} else {
  fmt.Println("No error to be had " + workItem) // Will not print until there is an item in the list
}

我想我一直都做对了。但是,如果有任何关于性能或更好的方法的意见或建议,我仍然会听到并很乐意听到他们的意见。

最佳答案

@JimB 实至名归。我切换了错误和成功处理程序。我给 BRPOP 命令的参数太少了。循环中的这段代码修复了它:

// We now import "log" now as well
// Inside the for loop...
if err != nil {
  log.Fatal(err) // This alerted me to the wrong # of arguments issue
} else {
  fmt.Println("No error to be had " + workItem) // Will not print until there is an item in the list
}

谢谢大家

关于node.js - 如何让 Go 应用程序等待 Redis 列表中的数据可用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29416837/

相关文章:

node.js - CircleCI无法运行 "claudia update"

Node.js、mongodb 和过滤查询

go - 在Goroutine : why should this work?中推迟对sync.WaitGroup.Wait()的调用

redis - 内部加入Redis

redis - 如何在毫秒级查询HBase表中的数据?

go - 在 Go 中重新连接到 Redis 订阅的惯用方法是什么?

javascript - 在 Node js 中使用标题、描述等内容上传 Vimeo 视频

javascript - 如何将 Socket.IO-Client 连接到 Sails.js 服务器?

macos - If 和 else 扰乱了 golang 中的变量作用域

go - 为什么在使用 select 并顺序将值输入 2 个 channel 时所有 goroutine 都处于休眠状态?