[C++]合理的设计和使用消息队列
生产者消费者问题,是永远的经典.
单纯让多个线程去竞争,占有资源然后处理,会让系统的复杂度变得相当复杂,并且整个系统的并发也很难控制.为了让系统简单化,流畅化,引入消息队列,而且这样,系统更具有相当高的吞吐量.因为做的事情简单而有效.
根据具体业务的不同,个人(认为)把消息队列分为1:1模型,还有就是N:M模型的.
如果消费者的消费能力非常高.个人认为就应该使用1:1的队列.这种队列足够简单,可以进行各种优化,比如避免动态内存分配,锁优化,使用lock-free等.这样可以让主循环的等待时间降到最低,使其可以专心致志进行各种逻辑处理.
有时,有些业务逻辑,不是很在乎时许,允许比较小的时间误差,而且消费能力很强的化,也是可以使用1:1的队列,不过生产者变成了n个,消费者还是一个.:-D 当然这种场景,不是非常多.
这边给出一个lock free的message queue.
如果消费者的消费能力比较差,还有一些业务,比如金钱相关的,比如数据库存档相关的,而且这样的系统,想要提高吞吐量,就只能使用N:M的模型.只不过这边把lock-free换成了mutex,虽然mutex有可能会陷入到内核,不过只要临界区足够小,操作足够轻量级,效率还是蛮高的.一般的系统,都不会在这边有瓶颈.
这边给出一个blocking queue的实现.
消费速度\时序 | 关心 | 不关心 |
消费速度慢 | blocking | blocking |
消费速度快 |
1:1 lock free N:M blcoking |
lock free |
其实很多业务,1:1的就足够快了.
PS: 其实N:M的lock free queue也是可以实现的,不过需要用到cas. fecth and add使不能实现n个并发的.另外,cas实现消息队列的复杂性相当高,收益也不是非常有效(在CPU核数较多的情况下),故放弃了实现多并发的lock free队列.
另外不关心时序,不是意味着一点都不关心,而是允许有一定的误差,比如10ms.
本来还想贴代码,想想算了,代码在github上开源了,可以自己去看实现.
https://github.com/egmkang/green_turtle/blob/master/green_turtle/blocking_queue.h
https://github.com/egmkang/green_turtle/blob/master/green_turtle/message_queue.h