我有一个使用 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/