🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
# 简介 beanstalkd ,一个轻量级、分布式的内存队列系统。 # 概念 - Tube 这是一个「管道」的概念,「管道」就是指「队列」,一个队列系统,并非只能有一个「队列」,就像我们一个数据库系统,不止一个库一样。 不同的「管道」,代表着不同的内容类型,比如,举前面下单功能中的实际例子,我们发短信、发邮件两种类型的任务,就需要有两个分别处理他们的消费者,自然,这条任务(消息)也就需要存储在两个「管道」中。 > 但是,这里的队列一词,我们不能把它与数据结构「队列」画上等号,这里的队列,类似于分类,用于区分 Job 的种类,而 beanstalkd 在底层根据 Job 状态进行存储时所用的「队列」才是数据结构上的队列。 这里,你可以把 Tube 想象成一个书架,专门用于存放某一类书本。而书架内部,又被分为好几个区域,分别用于存放看过和没看过的书。 其中,书架就是 Tube ,区域就是数据结构之队列。 - Job 「任务」的概念,就是指「消息」,它指存储在队列中的每一个具体成员,在前面的 demo 中,我们有设置一个 Job class ,那就是一个 Job 在代码中的呈现形式。 > 生产者生成 Job ,将它放入特定的 Tube 中,再由消费者监听(订阅)特定的 Tube ,从中接收 Job 。 # 特性 > 在介绍 beanstalkd 的特性之前,我们应确保,已经读 Tube 和 Job 有了比较深刻的认知。 beastalkd 拥有以下特性: - 优先级(priority) beanstalkd 支持设置 Job 的优先级。 我们知道消息队列会根据 Job 被放入的先后顺序,将 Job 发送给消费者,它们就像是一群排着队买票的人,谁先进去,谁先买票。 但是,beanstalkd 支持优先级的特性,赋予了 Job 插队的能力。 设定 Job 优先级之后,可以让该 Job 在一堆 Job 中,更优先被消费者接收。(当然,如果你设置的优先级更低,则更晚被接收) > 可以联想到实际场景:vip 和 普通用户,我们可以为 vip 用户设置更高的优先级,让它优先被消费者消费。 - 延迟(delay) beanstalkd 支持为 Job 设置延迟接收的属性,通常而言,生产者往消息队列中放入一条消息,只要有消费者空闲,就会被立马接收。 但 beanstalkd 的延迟特性,可以让 Job 在指定时间才被接收。 > 比如,你希望用户下单成功时,大约五分钟之后,才给它发送短信通知。 **这里需要注意,被消费者执行的时间,不仅仅取决于延迟特性,同样也受消费者接收频率影响** - 预留(bury) beanstalkd 支持设置 Job 的状态为预留,处于预留状态时,它不允许被消费,也不会被消费者接收。 > 比如,我们想实现顺序消费:先发短信,再发邮件,此时,我们可以在邮件消费者中,检查该 Job 是否已经发送过短信(存在短信发送记录),如果还没发送过,就把它设置为预留状态,等到之后条件满足(存在短信发送记录)后,再进行消费。 - 持久化(persistent data) beanstalkd 还可通过日志实现持久化,这样我们可以不必担心数据丢失,提升了消息可靠性。 至于如何操作,在后文会有介绍。 - 超时重发( time-to-run ,ttr ) beanstalkd 拥有 TTR 的特性,在前文《使用消息队列的注意事项》中有所提及。 ttr 也是提升消息可靠性的一种手段。 它指,在消费者接收到 Job 之后,没能在一定时间内处理完毕,此时,beanstalkd 会认为该 Job 处理失败,将它从 reserved 的状态重新调整到 ready 状态。 **这也是导致出现消息重复被消费的问题,因为消费者响应超时,可能由其它原因引起,比如网络原因,并不一定是真的处理失败了。** # 任务状态 - ready 此状态代表 Job 随时可以被消费者接收 - reserved 此状态指 Job 已被消费者接收,但消费者那边还没有给出反馈(还未执行结束),它不会被消费者接收 - delayed 此状态指 Job 处于延迟状态,等到时间到了,会转为 ready ,只有转为ready之后,才能被消费者接收 - buried 此状态指 Job 处于预留状态,它不会被消费者接收 - deleted 此状态指 Job 已经从 Tube 中被删除,实际上,它已经不存在了 # 安装 beanstalkd linux 安装 beanstalkd 并不难。 我们知道,linux 自定义安装(编译安装),一般经历这么几步: - wget (或者压缩包已经在目录下了) - tar 解压 - make && make install 那么,我们只需要下载你需要的版本的 beanstalkd 压缩包到,再解压,再编译安装,就行了。 这里,记录一下我安装的过程: ``` wget https://github.com/beanstalkd/beanstalkd/archive/v1.10.zip tar xzvf beanstalkd-1.10.zip cd beanstalkd-1.10 make && make install beanstalkd -v ``` 最后一个命令执行之后如果能够反馈给你 beanstalkd 的版本号,说明安装成功了,接下来就是启动 beanstalkd 的服务: ``` beanstalkd -l 0.0.0.0 -p 11300 -b /log/beanstalkd/binlog -F ``` **-l 指绑定的 ip ,默认为 127.0.0.1** **-p 指绑定的端口,默认端口 11300** -b 指开启 binlog 进行持久化,用于断电后恢复数据 -F 不把内存文件写入磁盘 更多的选项,可以通过 beanstalkd -h 查看 > 当然,你还可以直接使用 yum 或者 apt-get 来安装,更加方便。 **如果重复运行 beanstalkd -l -p 的命令,可以让 beanstalkd 同时监听多个 ip 和端口。** # 分布式 beanstalkd 的分布式,需要通过客户端自己实现。 即,比如你有 10 台消息队列服务器,此时,你需要全部部署上 beanstalkd ,并且,自己编写分布式的中间代码。 这就跟 memcached 的分布式一样。 # 重要提醒 默认情况下,我们的 beanstalkd 没有开启 binlog 的功能,且绑定的 ip 为 127.0.0.1 ,网上有很多文章说,如果安装 web 控制台的时候,无法连接 beanstalkd ,就把 127.0.0.1 改成 0.0.0.0 ,这是不对的。 这个 ip 是指 beanstalkd 监听(允许连接)的客户端,比如你的客户端 ip 为 155.22.98.28 ,此时,你设置 -l 为该 ip , 则,该 ip 可以访问 beanstalkd 的服务器。 如果改成 0.0.0.0 ,指不限制,那么,你的 beanstalkd 服务器就非常危险,任何 ip 都能访问进来。 这里,必须要知道一下,为什么改成 0.0.0.0 就可以访问了。 你可能需要根据你的部署架构来综合分析,如何设置这个 ip ,并理清你的内外网、物理机、虚拟机,这样才能设置最合理的 ip 。 另外,在部署环境里,如果非要设置 0.0.0.0 (均衡负载的情况下可能有多个客户端连接过来),此时,就需要通过网络环境上的 ip 白名单、端口等方式来过滤。 > 总的来讲,beanstalkd 的服务器没有一个账号密码体系,只有监听 ip 的方式,来鉴别它是否处理你的指令。所以,它非常纯洁,如果我们需要最大程度上控制安全,最好让 beanstalkd server 只允许本机访问,而外部则访问位于本机上的 client ,由 client 进行安全校验和连接 beanstalkd server 。 # 扩展阅读 [beanstalkd 工具](https://github.com/beanstalkd/beanstalkd/wiki/Tools) [对 windows 的支持](https://github.com/beanstalkd/beanstalkd/wiki/Windows-Support) [客户端类库大全](https://github.com/beanstalkd/beanstalkd/wiki/Client-Libraries) [beanstalkd 常见问题](https://github.com/beanstalkd/beanstalkd/wiki/FAQ) [高可用思路](https://blog.csdn.net/qguanri/article/details/50055479) > 为什么把它叫做高可用思路,因为思路指得学习,但具体的实现,建议根据自己的项目需求而定制,尽量不直接使用他人的源码部署到线上。