beanstalk 生命周期
Table of content:
About
Beanstalk 是一个高性能,轻量级的分布式内存队列系统,最初设计的目的是想通过后台异步执行耗时的任务来降低高容量 Web 应用系统的页面访问延迟。
- 协议,类 Memcached 协议, 非二进制安全
- 全内存, 可开启 binlog, 断电从 binlog 恢复数据
- 单线程, 使用 epoll/kqueue 来实现事件机制
核心概念和生命周期:
核心概念:
- job,一个需要异步处理的基本单元,job 要放在 tube 中。有多个生命周期,
- tube,一个任务队列, 可以通过
use tube_name
来进行切换 - producer,生产者,通过 put 将 job 放入 tube
1 | put <pri> <delay> <ttr> <bytes>\r\n |
- delay = 0,进入就绪(READY)队列, 可以直接被消费。
- dealy > 0, 进入延时队列(DELAYED), 等到延时时间到了之后自动迁移就绪队列。
- consumer,消费者,通过 reserve,bury,release,delete 来改变 job 状态
生命周期
beanstalk 一个 job 的生命周期: ready, reserved,delayed,buried
- ready, 等待被消费
- reserved, 如果 job 被取出,worker 将预定这个 job
- delayed, 延迟被消费,等待特定时间之后,状态再迁移为 ready状态
- buried, 等待唤醒,通常是 job 执行失败时
通常的状态:一个 job 进入到队列,是 ready 状态。reserved 是等待被消费,然后被消费后是删除
1 | put reserve delete |
还有一种可能的状态:
1 | put with delay release with delay |
这里面有几个有趣的 job stats:
- ttr(time-to-run) 任务超时重发,Beanstalkd 把任务返回给消费者后:消费者必须在预设的 TTR(time-to-run) 时间内发送 delete、release 或者 bury 命令改变任务状态;否则 Beanstalkd 会认为消息处理失败,任务将会被 release 到 ready 队列,其他消费者节点会执行执行。如果消费者预计在TTR时间内无法完成任务, 可以发送 touch 命令,以使 Beanstalkd 重新计算 TTR。Beanstalk 默认的 ttr 是 120s,也就是如果任务执行超过了 ttr,就有被重复执行的风险。
- priority,任务 (job) 可以有 0~2^32 个优先级,0 表示优先级最高。Beanstalkd 采用最大最小堆 (Min-max heap) 处理任务优先级排序, 任何时刻调用 reserve 命令的消费者总是能拿到当前优先级最高的任务, 时间复杂度为 O(logn)
- reserves, 被取出的次数
- kicks 被 kick 的次数
- timeouts, 任务 timeout 的次数(而这个在中文协议上翻译的是超时时间,是有严重问题的,在这个 MR 中提交了修复 https://github.com/beanstalkd/beanstalkd/pull/388)
- id, job id
Beanstalk service
1 | # install |
run service
1 | ᐅ beanstalkd help |
1 | beanstalkd -l 127.0.0.1 -p 11300 |
常见的问题
集群问题
跟 memcache 类似,没有 master-slave 方式,需要自己解决单点问题
timeout limit 的含义
中文翻译有一些严重问题,导致设计基于 Beanstalk 的离线任务框架的时候,timeout limit 默认值设计的并不是很合理。后来提交了 MR 进行修复 https://github.com/beanstalkd/beanstalkd/pull/388
怎么可以限制一个 Task 被执行的数量 ?怎样避免任务被反复执行 ?
一个任务可能被反复执行的场景有:
- 任务时间过长,超过了默认的 timeout 时间(120s)或者 task 设置的 ttr, 会被重新 release 到 ready 队列,等待被其他消费节点执行
- 任务执行过程中抛了异常,会进入 bury 状态,在一定时间内会重新 kick 到 ready 状态,等待被消费。
能够更准备代表一个任务被消费次数的是 reserves
,详见: https://github.com/kr/beanstalkd/blob/master/doc/protocol.txt#L81
todos
还可以从两个角度来扩展这个话题:
- beanstalk 一些源码阅读
- 工作中基于 beanstalk 的离线任务框架的简化版设计图
Reference and Recommendation
- 关于消息队列:
- 介绍各种消息队列 http://queues.io/
- 关于 Beanstalk
- Beanstalk 协议:https://github.com/beanstalkd/beanstalkd/blob/master/doc/protocol.txt
- Project: http://kr.github.io/beanstalkd/, Lan: C, Description: fast, light weighted task queue
- FAQ: https://github.com/kr/beanstalkd/wiki/faq
- Python 客户端:
- beanstalkc, Beanstalk Python client: https://github.com/earl/beanstalkc/blob/master/TUTORIAL.mkd
- blog:
- 一篇写的还不错的关于 Beanstalk 使用的博客 https://itbilu.com/other/relate/VkBat8I-X.html
- Beanstalk 的一部分源码分析 http://www.hulkdev.com/posts/think_in_beanstalkd
关于头图
拍摄自青岛极地海洋世界