我有一个使用Radix Redis client for Go的Go应用。它的工作是作为后台进程运行,并等待Redis列表添加项目以进行处理。
背景(随意跳过):我有一个Node.js网络应用,需要从外部API请求数据至少需要整个第二个或更多回应。我们不需要立即生成数据,因此我让Node应用程序将项目添加到Redis列表中,然后转到重要的内容。同时,我有一个Go应用程序应该在幕后运行,并在每次发现项目已添加到列表时执行一些工作。
现在它只是一个main
函数连接到Redis并使用Redis BRPOP
命令检查列表中是否有项目(因为我希望Redis阻塞而等待工作)。运行程序会导致建立连接,然后......
我需要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,
它无限打印上面这是有道理的,因为我有一个永无止境的循环但因为我使用阻止命令,我期待它的行为更像是推送。我希望循环只是暂停并等到队列中有一个项目,然后再继续下一次迭代。我对它的关注即使没有队列项也会继续循环,最终由于BRPOP
命令的持续攻击(尽管它是阻塞命令),最终进程将开始不必要地消耗资源并减慢Redis的速度。 p>
所以我想现在的新问题就是 - 在Redis列表(或我的临时队列)中等待新项目时,是否有更好的方法来保持Go程序的运行? - 以当前形式运行此程序会消耗更多资源吗和/或降低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
}
我想我一直在做这件事。但是,如果有任何关于表现的评论或建议或更好的方法,我仍然会听到并希望听到它们。
答案 0 :(得分:2)
@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
}
谢谢大家。