标签:redis 任务队列 brpop queue 优先级队列
在网站开发中,当页面需要进行如发送邮件、复杂数据运算等耗时较长的操作时会阻塞页面的渲染。为了避免用户等待太久,应该使用独立的线程来完成这类操作。不过一些编程语言或框架不易实现多线程,这时很容易就会想到通过其他进程来实现。设想有一个进程能够完成发邮件的功能,那么在页面中只需要想办法通知这个进程向指定的地址发送邮件就可以了。
通知的过程可以借助任务队列来实现。任务队列顾名思义,就是“传递任务的队列”。与任务队列进行交互的实体有两类,一类是生产者(producer),一类是消费者(consumer)。生产者会将需要处理的任务放入任务队列中,而消费者则不断地从任务队列中读入任务信息并执行。
行。由此实现了进程间的通信。
(2)易于扩展消费者可以有多个,而且可以分布在不同的服务器中,借此可以轻易地降低单台服务器的负载。
下面我们使用Redis实现任务队列
Redis的列表类型,使用LPUSH和RPOP命令实现队列。如果要实现任务队列,只需要让生产者将任务使用LPUSH命令加入到某个键中,另一边让消费者不断地使用RPOP命令从该键中取出任务即可。
在上面例子中,完成发邮件的任务需要知道收件地址、邮件主题和邮件正文。所以生产者需要将这三个信息组成对象并序列化成字符串,然后将其加入到任务队列中。而消费者则循环从队列中拉取任务,就像如下伪代码:
#无限循环读取任务队列中的内容 loop $task=RPOR queue if $task #如果任务队列中有任务则执行它 execute($task) else #如果没有则等待1秒以免过于频繁地请求数据 wait 1 second
BRPOP命令和RPOP命令相似,唯一的区别是当列表中没有元素时BRPOP命令会一直阻塞住连接,直到有新元素加入。如上段代码可改写为:
loop #如果任务队列中没有新任务,BRPOP命令会一直阻塞,不会执行execute()。 $task=BRPOP queue, 0 #返回值是一个数组(见下介绍),数组第二个元素是我们需要的任务。 execute($task[1])
当获得一个元素后BRPOP命令返回两个值,分别是键名和元素值。为了测试BRPOP命令,我们可以打开两个redis-cli实例,在实例A中:
redis A>BRPOP queue 0
键入回车后实例1会处于阻塞状态,这时在实例B中向queue中加入一个元素:
redis B>LPUSH queue task (integer) 1
1) "queue" 2) "task"
redis>LLEN queue (integer) 0
Redis优先级队列
当发送确认邮件和发送通知邮件(可以延迟)两种任务同时存在时,应该优先执行前者。为了实现这一目的,我们需要实现一个优先级队列。
BRPOP命令可以同时接收多个键,其完整的命令格式为BLPOP key [key …]timeout ,如BLPOP queue:1 queue:2 0。意义是同时检测多个键,如果所有键都没有元素则阻塞,如果其中有一个键有元素则会从该键中弹出元素。例如,打开两个redis-cli实例,在实例A中:
redis A>BLPOP queue:1 queue:2 queue:3 0
redis B>LPUSH queue:2 task (integer) 1
1) "queue:2" 2) "task"
redis>LPUSH queue:2 task1 1) (integer) 1 redis>LPUSH queue:3 task2 2) integer) 1
redis>BRPOP queue:1 queue:2 queue:3 0 1) "queue:2" 2) "task1"
loop $task = BRPOP queue:confirmation.email, queue:notification.email, 0 execute(task[1])
标签:redis 任务队列 brpop queue 优先级队列
原文地址:http://blog.csdn.net/wtyvhreal/article/details/43112735