消息队列初识

消息队列概述

消息队列中间件是分布式系统中重要的组件,主要解决应用耦合、异步消息、流量削锋等问题。实现高性能、高可用、可伸缩和最终一致性架构。是大型分布式系统不可缺少的中间件。
目前在生产环境,使用较多的消息队列有ActiveMQ、RabbitMQ、ZeroMQ、Kafka、MetaMQ、RocketMQ等。

使用场景

消息队列在实际应用中包括如下场景:

应用耦合

多应用间通过消息队列对同一消息进行处理,避免调用接口失败导致整个过程失败;(如:订单->库存)
具体场景:用户使用QQ相册上传一张图片,人脸识别系统会对该图片进行人脸识别,一般的做法是,服务器接收到图片后,图片上传系统立即调用人脸识别系统,调用完成后再返回成功,如下图所示:
消息队列初识_第1张图片
该方法有如下缺点:

  • 人脸识别系统被调失败,导致图片上传失败;
  • 延迟高,需要人脸识别系统处理完成后,再返回给客户端,即使用户并不需要立即知道结果;
  • 图片上传系统与人脸识别系统之间互相调用,需要做耦合;
    若使用消息队列:
    在这里插入图片描述
    客户端上传图片后,图片上传系统将图片信息如uin、批次写入消息队列,直接返回成功;而人脸识别系统则定时从消息队列中取数据,完成对新增图片的识别。 此时图片上传系统并不需要关心人脸识别系统是否对这些图片信息的处理、以及何时对这些图片信息进行处理。事实上,由于用户并不需要立即知道人脸识别结果,人脸识别系统可以选择不同的调度策略,按照闲时、忙时、正常时间,对队列中的图片信息进行处理。

异步处理

多应用对消息队列中同一消息进行处理,应用间并发处理消息,相比串行处理,减少处理时间;(点对多场景,广播场景(注册发短信,发邮件)等等)。

具体场景:用户为了使用某个应用,进行注册,系统需要发送注册邮件并验证短信。对这两个操作的处理方式有两种:串行及并行。
(1)串行方式:新注册信息生成后,先发送注册邮件,再发送验证短信;
在这里插入图片描述
在这种方式下,需要最终发送验证短信后再返回给客户端。
(2)并行处理:新注册信息写入后,由发短信和发邮件并行处理;
消息队列初识_第2张图片
在这种方式下,发短信和发邮件 需处理完成后再返回给客户端。
假设以上三个子系统处理的时间均为50ms,且不考虑网络延迟,则总的处理时间:
串行:50+50+50=150ms
并行:50+50 = 100ms
若使用消息队列:
消息队列初识_第3张图片
并在写入消息队列后立即返回成功给客户端,则总的响应时间依赖于写入消息队列的时间,而写入消息队列的时间本身是可以很快的,基本可以忽略不计,因此总的处理时间相比串行提高了2倍,相比并行提高了一倍;

限流削峰

应用于秒杀或抢购活动中,避免流量过大导致应用系统挂掉的情况;(根据服务承受度设置队列大小,超过了就返回活动结束了,咱们经常各大商城秒杀,心里还没有点B数吗)减少压力,避免服务挂掉。

具体场景:购物网站开展秒杀活动,一般由于瞬时访问量过大,服务器接收过大,会导致流量暴增,相关系统无法处理请求甚至崩溃。而加入消息队列后,系统可以从消息队列中取数据,相当于消息队列做了一次缓冲。
在这里插入图片描述
该方法有如下优点:

  • 请求先入消息队列,而不是由业务处理系统直接处理,做了一次缓冲,极大地减少了业务处理系统的压力;
  • 队列长度可以做限制,事实上,秒杀时,后入队列的用户无法秒杀到商品,这些请求可以直接被抛弃,返回活动已结束或商品已售完信息;

消息驱动的系统

系统分为消息队列、消息生产者、消息消费者,生产者负责产生消息,消费者(可能有多个)负责对消息进行处理;(分工处理(各自对应相应的队列),灵活应用(收到就处理/定时处理)) 。

具体场景:用户新上传了一批照片, 人脸识别系统需要对这个用户的所有照片进行聚类,聚类完成后由对账系统重新生成用户的人脸索引(加快查询)。这三个子系统间由消息队列连接起来,前一个阶段的处理结果放入队列中,后一个阶段从队列中获取消息继续处理。
在这里插入图片描述
该方法有如下优点:

  • 避免了直接调用下一个系统导致当前系统失败;
  • 每个子系统对于消息的处理方式可以更为灵活,可以选择收到消息时就处理,可以选择定时处理,也可以划分时间段按不同处理速度处理;

非实时性

当不需要立即获得结果,但是并发量又需要进行控制的时候,差不多就是需要使用消息队列的时候。主要解决了应用耦合、异步处理、流量削锋等问题。

消息队列使用模式

消息队列包括两种模式,点对点模式(point to point, queue)和发布/订阅模式(publish/subscribe,topic)。

点对点

点对点模式下包括三个角色:

  • 消息队列
  • 发送者 (生产者)
  • 接收者(消费者)
    消息队列初识_第4张图片

消息发送者生产消息发送到queue中,然后消息接收者从queue中取出并且消费消息。消息被消费以后,queue中不再有存储,所以消息接收者不可能消费到已经被消费的消息。
点对点模式特点:

  • 每个消息只有一个接收者(Consumer)(即一旦被消费,消息就不再在消息队列中);
  • 发送者和接收者间没有依赖性,发送者发送消息之后,不管有没有接收者在运行,都不会影响到发送者下次发送消息;
  • 接收者在成功接收消息之后需向队列应答成功,以便消息队列删除当前接收的消息;

发布/订阅

微信公众号(Topic),大伙(订阅者)订阅关注之后,微信公众号运营平台(发布者)发布信息后,大伙微信就都收到信息了,这里其实还分pull/push的。一个是主动推送,一个是被动拉取。

发布/订阅模式下包括三个角色:

  • 角色主题(Topic)
  • 发布者(Publisher)
  • 订阅者(Subscriber)

发布者将消息发送到Topic,系统将这些消息传递给多个订阅者。
消息队列初识_第5张图片
发布/订阅模式特点:

  • 每个消息可以有多个订阅者;
  • 发布者和订阅者之间有时间上的依赖性。针对某个主题(Topic)的订阅者,它必须创建一个订阅者之后,才能消费发布者的消息。
  • 为了消费消息,订阅者需要提前订阅该角色主题,并保持在线运行;

不同类型消息队列的对比

如图:
消息队列初识_第6张图片
详细介绍如下:

rabbitMQ

基于erlang开发,是采用Erlang语言实现的AMQP协议的消息中间件,最初起源于金融系统,用于在分布式系统中存储转发消息。RabbitMQ发展到今天,被越来越多的人认可,这和它在可靠性、可用性、扩展性、功能丰富等方面的卓越表现是分不开的。

优点:

  • 由于erlang语言的特性,mq性能较好,高并发;
  • 健壮、稳定、易用、跨平台、支持多种语言、文档齐全
  • 有消息确认机制和持久化机制,可靠性高
  • 高度可定制的路由;
  • 管理界面较丰富,在互联网公司也有较大规模的应用;
  • 社区活跃度高;

缺点:

  • 尽管结合erlang语言本身的并发优势,性能较好,但是不利于做二次开发和维护;
  • 实现了代理架构,意味着消息在发送到客户端之前可以在中央节点上排队。此特性使得RabbitMQ易于使用和部署,但是使得其运行速度较慢,因为中央节点增加了延迟,消息封装后也比较大;
  • 需要学习比较复杂的接口和协议,学习和维护成本较高;

activeMQ

基于java开发,是Apache出品的、采用Java语言编写的完全基于JMS1.1规范的面向消息的中间件,为应用程序提供高效的、可扩展的、稳定的和安全的企业级消息通信。不过由于历史原因包袱太重,目前市场份额没有后面三种消息中间件多,其最新架构被命名为Apollo,(京东的消息中间件就是基于activeMQ开发的)

优点

  • 跨平台(JAVA编写与平台无关有,ActiveMQ几乎可以运行在任何的JVM上)
  • 可以用JDBC:可以将数据持久化到数据库
  • 支持JMS :支持JMS的统一接口;
  • 支持自动重连;
  • 有安全机制:支持基于shiro,jaas等多种安全配置机制,可以对Queue/Topic进行认证和授权
  • 监控完善:拥有完善的监控,包括Web Console,JMX,Shell命令行,Jolokia的REST API;
  • 界面友善:提供的Web Console可以满足大部分情况,还有很多第三方的组件可以使用,如hawtio;

缺点

  • 社区活跃度不及RabbitMQ高;
  • 会出莫名其妙的问题,会丢失消息;
  • 不适合用于上千个队列的应用场景;

zeroMQ

基于C开发,号称史上最快的消息队列,基于C语言开发。ZeroMQ是一个消息处理队列库,可在多线程、多内核和主机之间弹性伸缩,虽然大多数时候我们习惯将其归入消息队列家族之中,但是其和前面的几款有着本质的区别,ZeroMQ本身就不是一个消息队列服务器,更像是一组底层网络通讯库,对原有的Socket API上加上一层封装而已。

优点

  • 号称最快的消息队列系统,尤其针对大吞吐量的需求场景
  • 单独部署或集成到应用中使用,不需要安装和运行一个消息服务器或中间件,因为你的应用程序将扮演了这个服务角色
  • 能够实现高级/复杂的队列,但是开发人员需要自己组合多种技术框架
  • 跨平台,多语言支持
  • 可作为Socket通信库使用

缺点

  • 仅提供非持久性的队列,也就是说如果down机,数据将会丢失

rocketMQ

基于java开发(阿里消息中间件), 是阿里开源的消息中间件,目前已经捐献个Apache基金会,它是由Java语言开发的,具备高吞吐量、高可用性、适合大规模分布式系统应用等特点,经历过双11的洗礼,实力不容小觑。

优点:

  • 单机支持 1 万以上持久化队列
  • RocketMQ 的所有消息都是持久化的,先写入系统 pagecache(页高速缓冲存储器),然后刷盘,可以保证内存与磁盘都有一份数据,访问时,直接从内存读取。
  • 模型简单,接口易用(JMS 的接口很多场合并不太实用)
  • 性能非常好,可以大量堆积消息在broker(集群中包含一个或多个服务器,这些服务器被称为broker)中;
  • 支持多种消费,包括集群消费、广播消费等。
  • 各个环节分布式扩展设计,主从HA(高可用性集群);
  • 开发度较活跃,版本更新很快。

缺点

  • 支持的客户端语言不多,目前是java及c++,其中c++不成熟;

  • RocketMQ社区关注度及成熟度也不及前两者;

  • 没有web管理界面,提供了一个CLI(命令行界面)管理工具带来查询、管理和诊断各种问题;

  • 没有在 mq 核心中去实现JMS等接口;

kafka

基于Scala和Java开发,起初是由LinkedIn公司采用Scala语言开发的一个分布式、多分区、多副本且基于zookeeper协调的分布式消息系统,现已捐献给Apache基金会。它是一种高吞吐量的分布式发布订阅消息系统,以可水平扩展和高吞吐率而被广泛使用。目前越来越多的开源分布式处理系统如Cloudera、Apache Storm、Spark、Flink等都支持与Kafka集成。

优点

  • 客户端语言丰富,支持java、.net、php、ruby、python、go等多种语言;
  • 性能卓越,单机写入TPS约在百万条/秒,消息大小10个字节;
  • 提供完全分布式架构, 并有replica机制, 拥有较高的可用性和可靠性, 理论上支持消息无限堆积;
  • 支持批量操作;
  • 消费者采用Pull方式获取消息, 消息有序, 通过控制能够保证所有消息被消费且仅被消费一次;
  • 有优秀的第三方Kafka Web管理界面Kafka-Manager;
  • 在日志领域比较成熟,被多家公司和多个开源项目使用;

缺点

  • Kafka单机超过64个队列/分区,Load会发生明显的飙高现象,队列越多,load越高,发送消息响应时间变长
  • 使用短轮询方式,实时性取决于轮询间隔时间;
  • 消费失败不支持重试;
  • 支持消息顺序,但是一台代理宕机后,就会产生消息乱序;
  • 社区更新较慢;

Redis

Redis的PUB/SUB机制,即发布-订阅模式。利用的Redis的列表(lists)数据结构。比较好的使用模式是,生产者lpush消息,消费者brpop消息,并设定超时时间,可以减少redis的压力。只有在Redis宕机且数据没有持久化的情况下丢失数据,可以根据业务通过AOF和缩短持久化间隔来保证很高的可靠性,而且也可以通过多个client来提高消费速度。但相对于专业的消息队列来说,该方案消息的状态过于简单(没有状态),且没有ack机制,消息取出后消费失败依赖于client记录日志或者重新push到队列里面。
redis不支持分组(这点很重要,在做负载均衡的时候劣势就体现出来),不过可以完全当做一个轻量级的队列使用,但redis他爹做了disque,可以去试一试。

消息队列优点和缺点

优点

  • 异步
  • 解耦
  • 削峰

缺点

  • 系统可用性降低:系统引入的外部依赖越多,越容易挂掉,本来你就是A系统调用BCD三个系统的接口就好了,人ABCD四个系统好好的,没啥问题,你偏加个MQ进来,万一MQ挂了咋整?MQ挂了,整套系统崩溃了,你不就完了么。
  • 系统复杂性提高:硬生生加个MQ进来,你怎么保证消息没有重复消费?怎么处理消息丢失的情况?怎么保证消息传递的顺序性?头大头大,问题一大堆,痛苦不已
  • 一致性问题:A系统处理完了直接返回成功了,人都以为你这个请求就成功了;但是问题是,要是BCD三个系统那里,BD两个系统写库成功了,结果C系统写库失败了,咋整?你这数据就不一致了。

消息队列使用总结

  • 消息队列不是万能的,对于需要强事务保证而且延迟敏感的,RPC是优于消息队列的。
  • 对于一些无关痛痒,或者对于别人非常重要但是对于自己不是那么关心的事情,可以利用消息队列去做。
  • 支持最终一致性的消息队列,能够用来处理延迟不那么敏感的“分布式事务”场景,而且相对于笨重的分布式事务,可能是更优的处理方式。
  • 当上下游系统处理能力存在差距的时候,利用消息队列做一个通用的“漏斗”,在下游有能力处理的时候,再进行分发。
  • 如果下游有很多系统关心你的系统发出的通知的时候,果断地使用消息队列吧。

消息队列及常见消息队列介绍
主流的消息队列MQ比较
消息中间件部署及比较
消息队列
消息队列技术介绍

你可能感兴趣的:(高性能服务器,性能调优)