队列

Redis实现任务队列(二)

2017-08-21  本文已影响14人  要读博士

概述

在处理Web客户端发送的命令请求时,某些操作的执行时间可能会比我们预期的更长一些。通过将待执行任务的相关信息放入队列里面,并在之后对队列进行处理,用户可以推迟执行那些需要一段时间才能完成的操作,这种将工作交给任务处理器来执行的做法称为任务队列。

延迟任务

    使用列表结构可以实现只能执行一种任务的队列,也可以实现通过调用不同回调函数来执行不同的任务队列,甚至还可以实现简单的优先级队列,但是有些时候,这些特性还不足以满足我们的需求。比如说:我们需要延迟处理某个队列,而不是立即就开始执行。

    有几种不同的方法可以为队列中的任务添加延迟性质,以下是三种最直接了当的方法。

    1、在任务信息中包含任务的执行时间,如果工作进程发现任务的执行时间尚未来临,那么它将在短暂等待之后,把任务重新推入队列里面。

    2、工作进程使用一个本地的等待列表来记录所有需要在未来执行的任务,并在每次进行while循环的时候,检查等待列表并执行那些已经到期的任务。

    3、把所有需要在未来执行的任务都添加到有序集合里面,并将任务的执行时间设置为分值,另外再使用一个进程来查找有序集合里面是否存在可以立即执行的任务,如果有的话,就从有序集合里面移除那个任务,并将它添加到适当的任务队列里面。

    因为无论是进行短暂的等待,还是将任务重新推入队列里面,都会浪费工作进程的时间,所以我们不会采用第一种方法。此外,因为工作进程可能会因为崩溃而丢失本地记录的所有带执行任务,所以我们也不会采用第二种方法。最后没因为使用有序集合的第三种方法最简单和直接,所以我们将采取这一方法。

    有序集合队列存储的每个被延迟的任务都是一个包含4个值的json列表。这4个值分别是:唯一标识符、处理任务的队列的名字,处理任务的回调函数的名字、传给回调函数的参数。在有序集合里面,任务的分值会被设置为任务的执行时间,而立即可执行的任务将被直接插入任务队列里面。

图5  将任务推入任务队列

    因为所有被延迟的任务都存储在同一个有序集合队列里面,所以程序只需要获取有序集合里面排名第一的元素以及该元素的分值就可以了:如果队列里没有任何任务,或者任务的执行时间尚未来临,那么程序将在短暂等待之后重试,如果任务的执行时间已到,那么程序将更具任务包含的标识符来后去一个细粒度锁,接着从有序集合里面移除要被执行的任务,并将它添加到适当的任务队列里面。

图6 任务入队列 图7 获得锁 图8 释放锁
上一篇 下一篇

猜你喜欢

热点阅读