本文介绍了Beanstalkd的功能和状态转换过程。
Philotic公司开发了beanstalkd,以改善Facebook应用程序的响应时间(超过950万用户)。Beanstalkd将最常见页面的平均响应时间缩短到原来的一小部分,从而显着改善了用户体验。
说明:本文使用的beanstalkd客户端是:python语言实现的beanstalkc。
beanstalkd是一个FIFO任务队列中间件,可以把job放入beanstalkd中,然后通过消费者来消费该队列中的job。放入beanstald中的job可以有多种状态。提供这些job的多种状态转换,可以让job的消费和使用更加灵活。
在beanstalkd中,队列用tube来代表,不同队列的job保存在不同的tube实体中。所有的tube保存在一个全局变量:tubes中。该变量的定义如下:
struct ms {
size_t used, cap, last;
void **items;
ms_event_fn oninsert, onremove;
};
如上面的数据结构所示,tube就保存在items中。items这里其实是tube指针(*tube)的数组。
tube结构如下所示:
struct tube {
uint refs;
char name[MAX_TUBE_NAME_LEN];
Heap ready;
Heap delay;
struct ms waiting; /* set of conns */
struct stats stat;
uint using_ct;
uint watching_ct;
int64 pause;
int64 deadline_at;
struct job buried;
};
job保存在对应的tube实体中(如何保存,请看后面的分解)。job有不同的状态,不同状态的job保存在tube中不同的变量中(如何完成保存,请参考后面的文章)。
正常状态的job生命周期如下图所示:
put reserve delete
-----> [READY] ---------> [RESERVED] --------> *poof*
READY状态
该状态由生产者产生。当生产者把job通过put放入tube时,此时job的状态是READY。
RESERVED状态
该状态由消费者产生。消费者通过reserve命令来订阅job,并消费job。在消费者进行订阅时,可以采用阻塞式订阅,也可以采取超时订阅。
一个job可能的完整生命周期如下图所示:
put with delay release with delay
----------------> [DELAYED] <------------.
| |
| (time passes) |
| |
put v reserve | delete
-----------------> [READY] ---------> [RESERVED] --------> *poof*
^ ^ | |
| \ release | |
| `-------------' |
| |
| kick |
| |
| bury |
[BURIED] <---------------'
|
| delete
`--------> *poof*
DELAYED状态
该状态是一个中间状态,当添加job时,设置了时延,job处于该状态。处于该状态的job,不能被消费,直到设置的时间超时,该job又恢复到READY状态。
BURIED状态
该状态是job的一个特殊状态,该状态下的job会被保存在一个特殊的队里中。处于该状态下的job不能被消费(reserve),直到该job被重新激活(通过kick命令)。
再说RESERVED状态
处于RESERVED状态的job,说明是已经有人订阅了。处于该状态下的job可以有几种方式:
(1)通过bury命令,把job隐藏起来,此时job不能被消费。
(2)通过release命令,把job放回到tube中,此时job处于READY状态。
状态 | 命令 | 说明 |
---|---|---|
DELAYED | put with delay | 添加超时时间的put命令(添加job) |
READY | put或release | release也可以加超时时间 |
BURIED | bury | 隐藏,被隐藏的job不能被订阅,直到被激活 |
RESERVED | reserve | 订阅job,被订阅的job不能再被订阅 |