使用Redis实现任务队列
2017-01-19 14:39
369 查看
使用Redis实现任务队列
说到队列很自然就能想到Redis的列表类型,3.4.2节介绍了使用LPUSH和RPOP命令实现队列的概念。如果要实现任务队列,只需要让生产者将任务使用LPUSH命令加入到某个键中,另一边让消费者不断地使用RPOP命令从该键中取出任务即可。
在小白的例子中,完成发邮件的任务需要知道收件地址、邮件主题和邮件正文。所以生产者需要将这三个信息组成对象并序列化成字符串,然后将其加入到任务队列中。而消费者则循环从队列中拉取任务,就像如下伪代码:
# 无限循环读取任务队列中的内容
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理解,这里不再赘述。
说到队列很自然就能想到Redis的列表类型,3.4.2节介绍了使用LPUSH和RPOP命令实现队列的概念。如果要实现任务队列,只需要让生产者将任务使用LPUSH命令加入到某个键中,另一边让消费者不断地使用RPOP命令从该键中取出任务即可。
在小白的例子中,完成发邮件的任务需要知道收件地址、邮件主题和邮件正文。所以生产者需要将这三个信息组成对象并序列化成字符串,然后将其加入到任务队列中。而消费者则循环从队列中拉取任务,就像如下伪代码:
# 无限循环读取任务队列中的内容
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理解,这里不再赘述。
相关文章推荐
- 关于redis中使用锁机制,( 实现分布式锁和任务队列)
- spring boot-使用redis的Keyspace Notifications实现定时任务队列
- Linux下Redis+crontab实现任务队列
- 使用NODEJS+REDIS开发一个消息队列以及定时任务处理
- 多线程与双端队列结合使用,实现持久化任务(3)
- 使用jedis实现Redis消息队列(MQ)的发布(publish)和消息监听(subscribe)
- Redis实现分布式锁 与 实现任务队列
- 放弃redis使用mongodb做任务队列支持增删改管理 推荐
- 用Redis实现分布式锁 与 实现任务队列
- 使用redis服务器实现队列(欢迎留言讨论)
- java redis使用之利用jedis实现redis消息队列
- Node.js + Redis Sorted Set 实现简单的任务队列
- Node.js 中使用 Redis 来实现定时任务
- PHP使用php-resque库配合Redis实现MQ消息队列的教程
- celery配合rabbitmq任务队列实现任务的异步调度执行[celery redis] 推荐
- java redis使用之利用jedis实现redis消息队列
- 用Redis实现分布式锁 与 实现任务队列
- Redis实现分布式锁与任务队列
- Redis使用总结(3):实现简单的消息队列
- PHP使用php-resque库配合Redis实现MQ消息队列的教程