消息中间件概述

什么是消息队列

队列数据结构

我们都学习过数据结构与算法相关的内容,消息队列从数据结构来看,就是一个由链表或是数组构成的一个先进先出的数据容器。由链表实现还是数组实现都没关系,它只要满足数据项是先进先出的特点,那么就可以认为它是一个队列结构。队列是只允许在一端进行插入操作、而在另一端进行删除操作的线性表。这个是队列较为正式的定义,这个定义使它满足先进先出特性。所谓线性表则表达的是队列元素之间的连接是线性的,元素的前进指针只能指向一个元素。更简单的解释是,元素与元素之间是一对一关系。

下图是一个由链表实现的单向链表队列

消息中间件概述_第1张图片

上面的队列,插入元素时总是插入到tail尾部,删除时问题从Head头部删除,要实现一个链表队列结构,只需要记录首尾指针指向的元素,元素与元素之间用指针连接即可。看到这里,我们就明白了什么是消息队列了,不过是一个把消息存储在队列结构里里的数据容器而已。

与队列结构相似是的栈结构,栈是后进先出的,栈(stack)是限定仅在表尾进行插入和删除操作的线性表。

消息中间件概述_第2张图片

如图,栈的操作因只能对表尾进行操作,因此只需要记录Top指针即可。增加元素(入栈)时,先让元素的前进指针指向Top指针指向的元素,再让Top指针指向自己即可。删除元素(出栈)时,让Top指针指向即将出栈的元素的前一个元素,然后将出栈元素前进指针断开即可。

生产者与消费者模式

我们可以利用队列数据结构实现消息内容的缓冲。所谓生产者与消费者模式,实际是消息队列的一种应用模式。生产者负责将消息发送到队列,消费者将队列里面的消息进行消费。大概如下图

消息中间件概述_第3张图片

 当然上面只是一个最简单的消息模型,点对点通信(P2P),实际应用得更多的是发布订阅模型,订阅者通常针对某一主题进行订阅。

消息中间件概述_第4张图片

什么是消息中间件

消息中间件首先是一款软件,比如常用的rabbitmq、rocketmq、Kafka等。中间件维基百科是这么定义的:

中间件(英语:Middleware),又译中间件、中介层,是一类提供系统软件和应用软件之间连接、便于软件各部件之间的沟通的软件,应用软件可以借助中间件在不同的技术架构之间共享信息与资源。中间件位于客户机服务器的操作系统之上,管理着计算资源和网络通信。

所以消息中间件就是应用与应用之间沟通消息的一种方式。应用与应用进行消息通讯方式有很多,比如TCP socket长连接通讯、Http短连接通讯等,消息中间件这种消息中转方式只是其中一种。是否应用消息中间件来进行通讯是基于现实应用场景考虑的,消息中间件通讯明显是一种异步通讯模型,消息从生产者发送到中间件,再到消费者消费消息,这个过程是异步不阻塞的。而像Http通讯是一种同步通讯,请求发起直到返回结果,程序才能继续往下执行。

消息中间件的优缺点

优点

消息中间件通常能给系统带来如下几种作用:

  • 异步处理提高系统响应性能

  • 削峰,避免高并发请求将系统压垮

  • 降低系统之间的耦合性

异步提高性能这个很容易理解,在微服务架构下,一个请求往往对应各种操作,涉及多个微服务。如果所有操作都是使用微服务RPC调用这种方式来通讯,极容易带来性能问题。因为微服务之间相互通讯不管是rest http通讯还是TCP长连接通讯,都是需要同步等待结果的,响应性能差。一旦这个长长的调用链路某个接口故障不响应,就会引发服务雪崩等现象。为解决这些问题,微服务架构下的系统往往引入了熔断、限流、消息中间件等手段来提高响应的性能及防止服务雪崩。举个例子,用户下单支付接口,通常会涉及创建订单、商品库存减少、用户积分增加等操作。如果所有操作都必须完成才给用户响应,那么给用户的感觉就是响应很慢,这个公司的程序员业务能力不行。避免流失用户,只能优化接口的响应速度,异步就是一个思路,将不重要的操作放到消息队列,由其它消费者微服务来处理,生产者只负责将消息传递到位即可,主接口只同步处理最重要,用户最关心的事情即可。比如用户积分的增加就压根不是用户那么想知道的事情,他可能只想知道到底下单成功了没。

削峰指的是,在短时间内,发生了高并发的请求,系统将请求放到消息队列,以可控的速率将请求消化。电商秒杀场景,通常都是使用消息队列来对请求峰值进行削平,因为消息中间件能堆积海量消息。如果没有消息中间件作为缓冲,系统极有可能被这种瞬时高并发请求给压垮。

消息中间件还能降低系统之间的耦合性。因为消息生产者只关心消息是否发送到中间件,至于消费者什么时候消费消息,生产者不关心,这样生产者和消费者之间就是没有直接耦合的,它们都只与中间件进行通讯。

缺点

  • 增加了系统复杂度,增加任务一款服务软件都必须考虑其高可用集群方案,必然增加系统复杂度

  • 一致性问题,因生产者不知道消费者的消费情况,假设消费者一直没消费消息,那么此时系统是数据不一致的。(使用消息队列通常是要牺牲强一致,只做到最终一致,从而提高系统性能的,因此需要找到性能与一致性的平衡点)

消息中间件应用场景

  • 电商秒杀,用于削峰

  • 发布订阅模型,这种场景比较多,通常是生产者将消息发布到消息中间件,同时多个不同业务的消费者对消息进行消费处理

  • 异步消息处理,系统解耦

简言之,只要符合消息中间件优点的场景都可以应用。

消息中间件选型

常用消息中间件有rabbitmq、rocketmq、kafka,究竟使用哪款消息中间件?我们可以对比各款中间件的优点和缺点,结合实际应用场景综合考虑,技术没有解决一切问题的银弹,适合对应场景的技术才能发挥其威力。

常见消息中间件对比

RabbitMQ RocketMQ Kafka
单机吞吐量 1w量级 10w量级 10w量级
开发语言 Erlang Java Java和Scala
消息延迟 微秒 毫秒 毫秒
消息丢失 可能性很低 参数优化后可以0丢失 参数优化后可以0丢失
消费模式 推拉 推拉 拉取
主题数量对吞吐量的影响 \ 几百上千个主题会对吞吐量有一个小的影响 几十上百个主题会极大影响吞吐量
可用性 高(主从) 很高(主从) 很高(分布式-副本机制)

通常在电商领域,选RocketMQ基本不会错 ,单机吞吐不输Kafka和消息延迟略逊rabbitmq,同时支持推拉的消费模型。Kafka基本上是应用于大数据领域对高吞吐的消息进行处理,电商领域、普通应用等场景都不推荐。最后是Rabbitmq,rabbitmq最大的好处是,消息延迟低,各种消息中间件该有的特性它都有,什么死信队列、延迟队列,发布订阅模型,主题订阅等等,个人理解是,它足够简单好用,功能强大,如果你的系统不是像某里那样的企业,需要单机应对10w级吞吐的,rabbitmq是一个很好的选择,并发能力强,延迟低,性能极佳。  当然,还有一个叫ActiveMQ的,我的建议是忘记它。

你可能感兴趣的:(消息中间件)