概述
本文从系统设计角度分析beanstalkd的优缺点,对beanstalkd的设计进行总结。
优点的总结
beanstalkd是基于内存的任务队列,性能较高。每个job有多种状态,状态之间可以相互转换。这些状态为job的使用者提供了使用的方便。
在网络事件驱动方面,使用异步,高效的epoll作为事件驱动框架,但使用的是单线程模式。
类似于数据库,beanstalkd把job保存在tube中,tube类似于关系型数据库中的数据库。
tube的job是通过堆这种数据结构进行组织的,每个tube提供两个类型的堆:delay和ready堆。delay堆中保存设置了ttr和delay的job。ready堆中保存的是已经准备好的job,这些job的状态是Ready。
可以改进的设计
内存管理问题
问题
beanstalkd没有内存管理模块,这对于后台服务程序来说是需要完善的。解决办法
- 使用第三方的内存管理模块,比如tcmalloc,或jemalloc等。
- 自己编写内存管理模块
堆的实现问题
- 问题
目前beanstalkd的job堆是通过数组来实现的,这种实现相对简单,但有一个问题:数组满时需要扩容,就需要申请一大块内存(这里是原来内存大小的2倍),并把现有的节点全部复制过去,这在高并发的情况下可能会出现问题。
- 解决办法
用另外一种方式来实现堆:比如链式堆。
网络事件模型问题
- 问题
网络事件驱动采用单线程的epoll模式,由于这个是单线程的,但有大量job需要处理时,导致其他事件来不及处理,可能导致阻塞。
- 解决办法
使用一个线程来接管连接请求,创建一个线程池来处理请求。把已经建立完成的连接交给后面的处理线程池接管,这样连接请求就不会阻塞了。而且可以把命令的处理分担到处理线程池中的线程中,从而实现了负载均衡。
其他数据结构的优化
另外,还有一些使用链表的数据结构,比如reserved的job,可以把这种结构改成hash表,这样可以提升查询性能。
持久化问题
目前beanstalkd的持久化还并不完善,特别是在数据量特别大的情况下。
总结
本文总结了beanstalkd的设计的优点和可以改进的地方。