当前位置: 首页 > 知识库问答 >
问题:

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

沈思博
2023-03-14

我有一个Go应用程序,使用Radix Redis客户端进行Go。它的任务是作为后台进程运行,并等待Redis列表添加项目以进行处理。

背景(请随意跳过):我有一个节点。需要从外部API请求数据的js web应用程序,已知至少需要一整秒钟或更长时间才能响应。数据不是立即需要的,所以我让Node应用程序向Redis列表中添加一个项目,然后继续处理重要的内容。同时,我有一个Go应用程序,应该在后台运行,每次发现列表中添加了一个项目时都会做一些工作。

现在,它只是一个main函数,它连接到Redis,并使用RedisBRPOP命令检查列表中是否有项目(因为我希望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循环,但因为我使用了blocking命令,我希望它的行为更像一个push。我希望循环只是暂停并等待,直到队列中有一个项目,然后再进入下一个迭代。我担心,即使没有队列项目,它也会继续循环,因为BRPOP命令不断涌现(尽管它是一个阻塞命令),最终该过程将开始不必要地消耗资源,并降低Redis的速度。

因此,我想现在的新问题是——在等待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
}

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

共有1个答案

姬俊远
2023-03-14

@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
}

谢谢大家。

 类似资料:
  • 我是Vertx的新手,正在探索使用事件总线的请求回复。 我想实现下面的流程 用户对数据的请求 控制器通过事件总线向redis处理器垂直体发送消息 redis处理器将等待n秒,直到redis中的值可用(将有一个后台进程持续刷新缓存,因此等待) redis处理器将向控制器发送回复 控制器响应用户 简而言之,我想做这样的事情: 现在我想在Vertx中实现这一点,因为Vertx可以异步运行。使用事件总线,

  • 2)使用了显式wait(WaitForelementPresent/WaitForVisible/ElementTobeClickable/wait for invisibility of element等)(所有可能的尝试) 3)使用Java脚本(window.angular.element('body').injector().get('$http').PendingRequests.Leng

  • 我有一个位于服务器上的bash脚本和一个将在该服务器上运行的Java应用程序。我的目标是从Java应用程序调用这个脚本两次,以便两者同时运行。 我有以下代码: 这应该通过bash调用脚本,在后台运行它,然后在第一个完成之前立即启动另一个脚本(脚本运行大约需要十秒钟)。这一切似乎都工作得很好。 问题是,然后我想等到两个后台进程都完成后再转到Java程序的下一行。我尝试了这个: 然而,“下一行代码”似

  • 问题内容: 如何让selenium等待日历小部件的加载?现在,我只是在将测试用例导出到junit程序后进行操作。 问题答案: 我会用 这将一直等待,直到元素出现在DOM中为止。 如果您需要检查元素是否可见,则最好使用

  • 问题内容: 如何让硒等待日历小部件的加载?现在,在将测试用例导出到junit程序后,我只是在做一个。 问题答案: 我会用 这将一直等待,直到元素出现在DOM中为止。 如果您需要检查元素是否可见,则最好使用

  • 我正在我的UI线程中调用一个方法。在这个方法中创建了一个新线程。我需要UI线程等待这个新线程完成,因为我需要这个线程的结果来继续UI线程中的方法。但我不想让UI在等待时冻结。有没有办法让UI线程在不忙的情况下等待?。