服务器公共组件实现 -- 消息队列

原创 2007年09月20日 22:10:00

  既然说到了消息队列,那我们继续来稍微多聊一点吧。

  我们所能想到的最简单的消息队列可能就是使用stl的list来实现了,即消息队列内部维护一个list和一个互斥锁,putMessage时将message加入到队列尾,getMessage时从队列头取一个message返回,同时在getMessage和putMessage之前都要求先获取锁资源。

  实现虽然简单,但功能是绝对满足需求的,只是性能上可能稍稍有些不尽如人意。其最大的问题在频繁的锁竞争上。

  对于如何减少锁竞争次数的优化方案,Ghost Cheng提出了一种。提供一个队列容器,里面有多个队列,每个队列都可固定存放一定数量的消息。网络IO线程要给逻辑线程投递消息时,会从队列容器中取一个空队列来使用,直到将该队列填满后再放回容器中换另一个空队列。而逻辑线程取消息时是从队列容器中取一个有消息的队列来读取,处理完后清空队列再放回到容器中。

  这样便使得只有在对队列容器进行操作时才需要加锁,而IO线程和逻辑线程在操作自己当前使用的队列时都不需要加锁,所以锁竞争的机会大大减少了。

  这里为每个队列设了个最大消息数,看来好像是打算只有当IO线程写满队列时才会将其放回到容器中换另一个队列。那这样有时也会出现IO线程未写满一个队列,而逻辑线程又没有数据可处理的情况,特别是当数据量很少时可能会很容易出现。Ghost Cheng在他的描述中没有讲到如何解决这种问题,但我们可以先来看看另一个方案。

  这个方案与上一个方案基本类似,只是不再提供队列容器,因为在这个方案中只使用了两个队列,arthur在他的一封邮件中描述了这个方案的实现及部分代码。两个队列,一个给逻辑线程读,一个给IO线程用来写,当逻辑线程读完队列后会将自己的队列与IO线程的队列相调换。所以,这种方案下加锁的次数会比较多一些,IO线程每次写队列时都要加锁,逻辑线程在调换队列时也需要加锁,但逻辑线程在读队列时是不需要加锁的。

  虽然看起来锁的调用次数是比前一种方案要多很多,但实际上大部分锁调用都是不会引起阻塞的,只有在逻辑线程调换队列的那一瞬间可能会使得某个线程阻塞一下。另外对于锁调用过程本身来说,其开销是完全可以忽略的,我们所不能忍受的仅仅是因为锁调用而引起的阻塞而已。

  两种方案都是很优秀的优化方案,但也都是有其适用范围的。Ghost Cheng的方案因为提供了多个队列,可以使得多个IO线程可以总工程师的,互不干扰的使用自己的队列,只是还有一个遗留问题我们还不了解其解决方法。arthur的方案很好的解决了上一个方案遗留的问题,但因为只有一个写队列,所以当想要提供多个IO线程时,线程间互斥地写入数据可能会增大竞争的机会,当然,如果只有一个IO线程那将是非常完美的。 

用STL设计消息队列、优先级消息队列、资源分配管理器

STL库老早已经成为C++的一部分,在使用C++开发项目的过程中,很多人还在犹豫要不要使用STL库,觉得STL库很难,其实不然。我工作的项目中现在大量使用STL库,STL使用调试简单,高效,可以减少重...
  • xiaoding133
  • xiaoding133
  • 2014年09月27日 15:07
  • 2619

C++多线程框架(三)--------- 消息队列

首先,本文提到的代码的github地址为: https://github.com/wyh267/Cplusplus_Thread_Lib 之前,多线程一些基本的东西,包括线程创...
  • u012377333
  • u012377333
  • 2014年07月28日 15:38
  • 1299

Linux进程间通信与同步

半双工管道 管道是一种把两个进程之间的标准输入和标准输出链接起来的机制。 由于管道仅仅是把某个进程的输出和另外一个进程的输入相连接的单项通信的方法,故称之为“半双工”; 由于进程A和进程B都能够访问管...
  • u011405813
  • u011405813
  • 2014年02月05日 23:41
  • 821

消息队列设计与实现

消息队列设计与实现
  • gsllovefly
  • gsllovefly
  • 2016年04月16日 11:45
  • 587

C++多线程框架(三)--------- 消息队列

首先,本文提到的代码的github地址为: https://github.com/wyh267/Cplusplus_Thread_Lib 之前,多线程一些基本的东西,包括线程创建,...
  • ygrx
  • ygrx
  • 2013年05月23日 13:19
  • 20019

分布式消息队列(Message Queue)系统:kafka扫盲

分布式系统很重要的一个设计原则是松耦合,即尽量减少子系统间的依赖。这样各个子系统可以相互独立的进行演进,维护,重用等。Message Queue (MQ)是一种很好的解耦手段。要了解MQ在系统整合中的...
  • jdbc
  • jdbc
  • 2014年10月01日 12:01
  • 1830

消息队列(Message Queue)基本概念和使用场景分析

背景   之前做日志收集模块时,用到flume。另外也有的方案,集成kafaka来提升系统可扩展性,其中涉及到消息队列当时自己并不清楚为什么要使用消息队列。而在我自己提出的原始日志采集方案中不适...
  • jaryle
  • jaryle
  • 2016年08月17日 10:44
  • 2338

消息队列MQ实践----实现Queue(队列消息)和Topic(主题消息)两种模式

之前有篇文件介绍了生产消费者模式(http://blog.csdn.net/canot/article/details/51541920),当时是通过BlockingQueue阻塞队列来实现,以及在R...
  • canot
  • canot
  • 2016年12月11日 12:04
  • 8389

消息队列技术终结者(二)—JMS中队列(Queue)和主题(Topic)的区别

消息队列技术终结者(二)—JMS中队列(Queue)和主题(Topic)的区别
  • wangshuxuncom
  • wangshuxuncom
  • 2014年12月27日 21:02
  • 4733

利用DelayQueue实现延时消息队列(简易版MQ)

利用DelayQueue实现延时消息队列(简易版MQ)
  • caicongyang
  • caicongyang
  • 2016年02月10日 19:46
  • 3478
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:服务器公共组件实现 -- 消息队列
举报原因:
原因补充:

(最多只允许输入30个字)