消息中间件:消息队列(Message Queue)解读

什么是消息队列呢?

解读一下:队列,应该都知道,一种先进先出的数据结构。

那什么是消息队列呢?可以简单理解为:当有大批的数据请求处理的时候,我们作为管理人员,必须保证整个处理业务的有序进行,且还要保证每个数据都能正常处理。

那么我们开发人员就要制定一套处理机制:“排队,先来的先处理”。

生产服务器不断的往MQ中放进去数据,那么消费服务器就需要不断的从MQ中取出数据进行处理。

 

那么消息队列的常见的业务场景有哪些呢?

我们可以从业务痛点来进行说明,在分布式应用中,很多服务之间都是相互调用的,很有可能一个业务逻辑我们需要使用到多个服务,那么我作为当前业务的主服务器,我需要对其他几个服务发送数据,那么我还需要进行对这几个服务的监控,需要考虑多方因素导致的消息发送失败,然后对其发送失败是否需要考虑失败处理措施...等等等。倘若这时候,又一个新的服务加进这个业务逻辑中,也需要这个消息,那么我主服务还需要对代码逻辑的修改,来将新服务也给发送一份消息,倘若又有一个?又有N个呢?

这肯定是不行的,程序猿会掉头发了,天天改代码,改一些毫无意义的代码。

那么这个时候就需要一种编程思想的处理:解耦

那么具体的处理方案就是使用:消息队列来进行解耦了。

具体方案如下:

第一步,我们可以使用一个消息队列放在主服务和其他消费服务中间,我主服务将断绝与其他服务的直接关系。我主服务作为一名生产者,只需要将我需要发送的消息,挨个放到消息队列服务中,然后就不管了,至于哪些消费者需要这些消息,你们自己去消息队列中取就是了。这样就对服务间的耦合性降低,从而解耦。但是此处会有一个弊端:如果某个消费者服务没有取到数据,造成了数据丢失,那么我生产者服务是完全不知晓的,也没有办法进行重发的。这也需要另外一些服务方案进行处理了。

对于为了解耦,使用消息队列的业务场景在我们实际的开发中屡见不鲜,很多,在本人开发的项目中,有一个场景很能代表,就是检测服务,和算法服务。检测服务负责将硬件领域检测到的数据收集,将其放到消息队列中去,然后算法服务不断的发现队列中存在需要分析的数据,不断的取出数据,然后分析完成会放到缓存和DB中,检测服务发现缓存中存在该体检的分析后数据了,那么将反馈给用户。当然消息队列的弊端也体现出来了,由于某些大型的活动,再加上体检高峰期,消费者跟不上生产者的步伐,导致体检数据大量堆积在消息队列中,算法服务器分析不过来的时候,只能挨个正常速度慢悠悠分析,然后生产者那边又不知道什么情况,只能以为算法服务器殆机了,作为用户的角度认为,你这个系统不行,没有用。那么这个时候,我们需要做一些应急处理措施,提醒措施,目前我们采用的是一种消息队列超过5条就立即应急预警。然后采用异步线程方式给用户延迟处理数据。这也是我们接下来要说的另外一个消息队列的核心特点了:异步。

 

异步

异步这个机制,必须要用的,这样想想,作为一个主服务,我还需要考虑其他服务都解决了,并且反馈了结果之后我才给用户进行响应,这这这,这样写代码,在古代是要被活活打死的。

你这样想想,我主服务接收到用户的请求5ms,主服务把数据进行IO操作200ms,然后发送给服务A,它又进行IO操作300ms,然后我又把数据发送给服务B,它又进行了IO操作200ms,然后我又把数据发送给了服务C,它也不厌其烦的进行了一些IO操作...你想想,主服务是不是无语了??,这样如果单线程的走,那么是不是用户那边收到请求需要5+200+300+200=··ms,这用户体验来说,太差了,作为开发者来说,要让用户无感操作。且整个处理流程,一般来说,必须保证在200ms以内。

那么我们如果使用消息队列,那么我主服务直接将消息放到MQ中,耗时3ms,然后响应用户,那么就只是3+5=8ms,对于用户角度来说,就是一个静态网页嘛。至于服务ABC分别在对应他们的消息队列中取数据,那你自己开线程跑就是了。好了之后,我后面取数据就是了。

 

削峰

这个问题,在解耦的实际案例中说到了,就是请求服务,在该来的时候不来,要么不来,要么一下全来了

如果是普通处理方案,用户突然一下发起了8k+的请求,这这这,我算法服务器闲时闲,忙时忙死啊。

一般的MySQL执行操作,顶多支撑每秒2k+就是很厉害了。如果直接搞到每秒8k+,那么mysql将直接死掉。那么如果一般时间来说,在下午的时候,1w的用户在线上同时操作,顶天每秒50个请求,那这个对于整个系统来说,就是小儿科了。但是这种情况只是理想状态。

 

那么我们使用MQ的好处呢?

如果使用消息队列,每秒8k+个请求写入,那么算法服务器每秒最多处理2k个,那么算法服务器就一个2k,一个2k的拉取,一个个处理,这样,即使是高峰期,也不会把服务器搞崩掉,但是此处会有一个大问题,就是如果在中文高峰期的时候,那可能就会有几百万,几千万的消息积压在队列中,这个时候,算法服务器还是慢悠悠的2k,2k,2k。。。。急死人。那么我们就需要考虑其他高可用的方案了,比如再开几台算法服务器等方案。当然,平摊一下,相对于吧高峰期的队列请求给平摊到后面的部分时段。这也是“削峰”的一个概念。

 

 

好处如上,那么消息队列有什么弊端呢?

其实在上面的时候,已经说明了,总结来说:

1.系统的可用性降低(整个业务逻辑,全部依赖于消息队列,如果消息队列一挂,整个系统就崩了)

2.系统复杂度提高(万一消息丢失咋办?万一重复消费?)

3.一致性问题(万一消费者A消费了?BCD分神了呢?这样不就顺序性掉了吗?)

 

总结来说

所以说消息队列是一种复杂的中间件技术架构,这也和很多的架构技术的特性类似,使用这类提升开发效率,系统运行效率的技术,同时也会带来一定的维护成本,类似分布式,服务的分离确实加大了业务的处理的专一性,但是无疑也加大了系统的维护性。

 

关于中间件有什么技术实现:(拷贝而来)

Kafka、ActiveMQ、RabbitMQ、RocketMQ 有什么优缺点?

特性 ActiveMQ RabbitMQ RocketMQ Kafka
单机吞吐量 万级,比 RocketMQ、Kafka 低一个数量级 同 ActiveMQ 10 万级,支撑高吞吐 10 万级,高吞吐,一般配合大数据类的系统来进行实时数据计算、日志采集等场景
topic 数量对吞吐量的影响     topic 可以达到几百/几千的级别,吞吐量会有较小幅度的下降,这是 RocketMQ 的一大优势,在同等机器下,可以支撑大量的 topic topic 从几十到几百个时候,吞吐量会大幅度下降,在同等机器下,Kafka 尽量保证 topic 数量不要过多,如果要支撑大规模的 topic,需要增加更多的机器资源
时效性 ms 级 微秒级,这是 RabbitMQ 的一大特点,延迟最低 ms 级 延迟在 ms 级以内
可用性 高,基于主从架构实现高可用 同 ActiveMQ 非常高,分布式架构 非常高,分布式,一个数据多个副本,少数机器宕机,不会丢失数据,不会导致不可用
消息可靠性 有较低的概率丢失数据 基本不丢 经过参数优化配置,可以做到 0 丢失 同 RocketMQ
功能支持 MQ 领域的功能极其完备 基于 erlang 开发,并发能力很强,性能极好,延时很低 MQ 功能较为完善,还是分布式的,扩展性好 功能较为简单,主要支持简单的 MQ 功能,在大数据领域的实时计算以及日志采集被大规模使用

综上,各种对比之后,有如下建议:

一般的业务系统要引入 MQ,最早大家都用 ActiveMQ,但是现在确实大家用的不多了,没经过大规模吞吐量场景的验证,社区也不是很活跃,所以大家还是算了吧,我个人不推荐用这个了;

后来大家开始用 RabbitMQ,但是确实 erlang 语言阻止了大量的 Java 工程师去深入研究和掌控它,对公司而言,几乎处于不可控的状态,但是确实人家是开源的,比较稳定的支持,活跃度也高;

不过现在确实越来越多的公司,会去用 RocketMQ,确实很不错(阿里出品),但社区可能有突然黄掉的风险,对自己公司技术实力有绝对自信的,推荐用 RocketMQ,否则回去老老实实用 RabbitMQ 吧,人家有活跃的开源社区,绝对不会黄。

所以中小型公司,技术实力较为一般,技术挑战不是特别高,用 RabbitMQ 是不错的选择;大型公司,基础架构研发实力较强,用 RocketMQ 是很好的选择。如果是大数据领域的实时计算、日志采集等场景,用 Kafka 是业内标准的,绝对没问题,社区活跃度很高,绝对不会黄,何况几乎是全世界这个领域的事实性规范。

posted @ 2019-10-10 10:52  CHANGEMAX  阅读(667)  评论(0编辑  收藏  举报