当前位置:嗨网首页>书籍在线阅读

20-使用Redis实现任务队列

  
选择背景色: 黄橙 洋红 淡粉 水蓝 草绿 白色 选择字体: 宋体 黑体 微软雅黑 楷体 选择字体大小: 恢复默认

4.4.2 使用Redis实现任务队列

说到队列很自然就能想到Redis的列表类型,3.4.2节介绍了使用 LPUSHRPOP 命令实现队列的概念。如果要实现任务队列,只需要让生产者将任务使用 LPUSH 命令加入到某个键中,另一边让消费者不断地使用 RPOP 命令从该键中取出任务即可。

在小白的例子中,完成发邮件的任务需要知道收件地址、邮件主题和邮件正文。所以生产者需要将这3个信息组成对象并序列化成字符串,然后将其加入到任务队列中。而消费者则循环从队列中拉取任务,就像如下伪代码:

# 无限循环读取任务队列中的内容
loop
  $task = RPOR queue
  if $task
     # 如果任务队列中有任务则执行它
    execute($task)
  else
     # 如果没有则等待1秒以免过于频繁地请求数据
    wait 1 second

到此一个使用Redis实现的简单的任务队列就写好了。不过还有一点不完美的地方:当任务队列中没有任务时消费者每秒都会调用一次 RPOP 命令查看是否有新任务。如果可以实现一旦有新任务加入任务队列就通知消费者就好了。其实借助 BRPOP 命令就可以实现这样的需求。

BRPOP 命令和 RPOP 命令相似,唯一的区别是当列表中没有元素时 BRPOP 命令会一直阻塞住连接,直到有新元素加入。如上段代码可改写为:

loop
  # 如果任务队列中没有新任务,BRPOP命令会一直阻塞,不会执行execute()。
  $task = BRPOP queue, 0
  # 返回值是一个数组(见下介绍),数组第二个元素是我们需要的任务。
  execute($task[1])

BRPOP 命令接收两个参数,第一个是键名,第二个是超时时间,单位是秒。当超过了此时间仍然没有获得新元素的话就会返回 nil 。上例中超时时间为 " 0 " ,表示不限制等待的时间,即如果没有新元素加入列表就会永远阻塞下去。

当获得一个元素后 BRPOP 命令返回两个值,分别是键名和元素值。为了测试 BRPOP 命令,我们可以打开两个redis-cli实例,在实例 A 中:

redis A> BRPOP queue 0 

键入回车后实例1会处于阻塞状态,这时在实例B中向 queue 中加入一个元素:

redis B> LPUSH queue task (integer) 1

LPUSH 命令执行后实例 A 马上就返回了结果:

1) "queue"
2) "task"

同时会发现 queue 中的元素已经被取走:

redis> LLEN queue (integer) 0

除了 BRPOP 命令外,Redis还提供了 BLPOP ,和 BRPOP 的区别在与从队列取元素时 BLPOP 会从队列左边取。具体可以参照 LPOP 理解,这里不再赘述。