rabbitMQ的相关知识点及概念


文章目录

  • rabbitMQ的相关知识点及概念
  • 【一】几种流行的中间件介绍
  • 【二】RabbitMQ高性能的原因
  • 【三】AMQP协议的核心概念
  • 【四】RabbitMQ的命名行,管控台
  • 【五】Exchange和路由Key
  • 【六】保证信息100%投递成功
  • 【七】幂等性
  • 【八】RabbitMQ的主要作用


【一】几种流行的中间件介绍

当前使用较多的消息队列有RabbitMQ、RocketMQ、ActiveMQ、Kafka

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

缺点:

1、尽管结合 Erlang 语言本身的并发优势,性能较好,但是不利于做二次开发和维护;
2、实现了代理架构,意味着消息在发送到客户端之前可以在中央节点上排队。此特性使得RabbitMQ易于使用和部署,但是使得其运行速度较慢,因为中央节点 增加了延迟,消息封装后也比较大;需要学习比较复杂的接口和协议,学习和维护成本较高。
  • RocketMQ
    优点:
1、单机支持1万以上持久化队列;
2、RocketMQ的所有消息都是持久化的,先写入系统PAGECACHE,然后刷盘,可以保3、证内存与磁盘都有一份数据,而访问时,直接从内存读取。
4、模型简单,接口易用(JMS的接口很多场合并不太实用);
5、性能非常好,可以允许大量堆积消息在Broker中;
6、支持多种消费模式,包括集群消费、广播消费等;
7、各个环节分布式扩展设计,支持主从和高可用;
8、开发度较活跃,版本更新很快。

缺点:

1、支持的 客户端语言不多,目前是Java及C++,其中C++还不成熟;
2、RocketMQ社区关注度及成熟度也不及前两者;
3、没有Web管理界面,提供了一个 CLI (命令行界面) 管理工具带来查询、管理和诊断各种问题;
4、没有在MQ核心里实现JMS等接口;
  • ActiveMQ
    优点:
1、跨平台(JAVA编写与平台无关,ActiveMQ几乎可以运行在任何的JVM上);
2、可以用JDBC:可以将数据持久化到数据库。虽然使用JDBC会降低ActiveMQ的性能,但是数据库一直都是开发人员最熟悉的存储介质;
3、支持JMS规范:支持JMS规范提供的统一接口;
4、支持自动重连和错误重试机制;
5、有安全机制:支持基于shiro,jaas等多种安全配置机制,可以对Queue/Topic进行认证和授权;
6、监控完善:拥有完善的监控,包括WebConsole,JMX,Shell命令行,Jolokia的RESTful API;
7、界面友善:提供的WebConsole可以满足大部分情况,还有很多第三方的组件可以使用,比如hawtio;

缺点:

1、社区活跃度不及RabbitMQ高;
2、根据其他用户反馈,会出莫名其妙的问题,会丢失消息;
3、目前重心放到activemq6.0产品Apollo,对5.x的维护较少;
4、不适合用于上千个队列的应用场景;
  • Kafka
    优点:
1、客户端语言丰富:支持Java、.Net、PHP、Ruby、Python、Go等多种语言;
2、高性能:单机写入TPS约在100万条/秒,消息大小10个字节;
3、提供完全分布式架构,并有replica机制,拥有较高的可用性和可靠性,理论上支持消息无限堆积;
4、支持批量操作;
5、消费者采用Pull方式获取消息。消息有序,通过控制能够保证所有消息被消费且仅被消费一次;
6、有优秀的第三方KafkaWeb管理界面Kafka-Manager;
7、在日志领域比较成熟,被多家公司和多个开源项目使用。

缺点:

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



使用场景:
1、RocketMQ定位于非日志的可靠消息传输(日志场景也OK),目前RocketMQ在阿里集团被广泛应用在订单,交易,充值,流计算,消息推送,日志流式处理,binglog分发等场景。

2、Kafka是LinkedIn开源的分布式发布-订阅消息系统,目前归属于Apache定级项目。Kafka主要特点是基于Pull的模式来处理消息消费,追求高吞吐量,一开始的目的就是用于日志收集和传输。0.8版本开始支持复制,不支持事务,对消息的重复、丢失、错误没有严格要求,适合产生大量数据的互联网服务的数据收集业务。

3、RabbitMQ是使用Erlang语言开发的开源消息队列系统,基于AMQP协议来实现。AMQP的主要特征是面向消息、队列、路由(包括点对点和发布/订阅)、可靠性、安全。AMQP协议更多用在企业系统内,对数据一致性、稳定性和可靠性要求很高的场景,对性能和吞吐量的要求还在其次。

【二】RabbitMQ高性能的原因

  • 可靠性:提供了多种技术可以让你在性能和可靠性之间进行权衡。这些技术包括持久性机制、投递确认、发布者证实和高可用性机制;
  • 灵活的路由:消息在到达队列前是通过交换机进行路由的。RabbitMQ为典型的路由逻辑提供了多种内置交换机类型。如果你有更复杂的路由需求,可以将这些交换机组合起来使用,你甚至可以实现自己的交换机类型,并且当做RabbitMQ的插件来使用;
  • 消息集群:在相同局域网中的多个RabbitMQ服务器可以聚合在一起,作为一个独立的逻辑代理来使用;
  • 队列高可用:队列可以在集群中的机器上进行镜像,以确保在硬件问题下还保证消息安全;
  • 支持多种协议:支持多种消息队列协议;
  • 支持多种语言:用Erlang语言编写,支持只要是你能想到的所有编程语言;
    = 管理界面:RabbitMQ有一个易用的用户界面,使得用户可以监控和管理消息Broker的许多方面;
  • 跟踪机制:如果消息异常,RabbitMQ 提供消息跟踪机制,使用者可以找出发生了什么;
  • 插件机制:提供了许多插件,来从多方面进行扩展,也可以编写自己的插件。

【三】AMQP协议的核心概念

架构图:

springcloud rabbitmq持久化 rabbitmq持久化缺点_消息队列


消息流转过程:

springcloud rabbitmq持久化 rabbitmq持久化缺点_消息队列_02


相关概念:

  • Broker:简单来说就是消息队列服务器实体。
  • Exchange:消息交换机,它指定消息按什么规则,路由到哪个队列。
  • Queue:消息队列载体,每个消息都会被投入到一个或多个队列。
  • Binding:绑定,它的作用就是把exchange和queue按照路由规则绑定起来。
  • Routing Key:路由关键字,exchange根据这个关键字进行消息投递。
  • vhost:虚拟主机,一个broker里可以开设多个vhost,用作不同用户的权限分离。
  • producer:消息生产者,就是投递消息的程序。
  • consumer:消息消费者,就是接受消息的程序。
  • channel:消息通道,在客户端的每个连接里,可建立多个channel,每个channel代表一个会话任务。

消息队列的使用过程大概如下:

  • 客 户端连接到消息队列服务器,打开一个channel。
  • 客户端声明一个exchange,并设置相关属性。
  • 客户端声明一个queue,并设置相关属性。
  • 客户端使用routing key,在exchange和queue之间建立好绑定关系。
  • 客户端投递消息到exchange。

【四】RabbitMQ的命名行,管控台

  • 基础服务的命令操作
rabbitmqctl stop_app:关闭应用

rabbitmqctl start_app:启动应用

rabbtmqctl status:节点状态

rabbitmqctl add_user username password:添加用户

rabbitmqctl list_users:列出所有用户

rabbitmqctl delete_user username:删除用户

rabbitmqctl clear_permissions - p vhostpath username: 清除用户权限

rabbitmqctl list_user_permissions_username: 列出用户权限

rabbitmqctl change_password username newpassword:修改密码

rabbitmqctl set_permissions -p vhostpath username "." "." ".*" :设置用户权限

涉及的用户命令还有许多,这里就不一一列举了。
  • 对虚拟主机操作
rabbitmqctl add_vhost vhostpath:创建虚拟主机

rabbitmqctl list_vhosts:列出所有虚拟主机

rabbitmqctl list_permissions -p vhostpath:列出虚拟主机上所有权限

rabbitmqctl delete_vhost vhostpath:删除虚拟主机
  • 队列操作
rabbitmqctl list_queues:查看所有队列信息

rabbitmqctl -p vhostpath purge_queue bule:清除队列里的消息
  • 高级操作
rabbitmqctl reset:移除所有数据,要在rabbitmqctl stop_app之后使用

rabbitmqctl join_clust [--ram]:组成集群命令

rabbitmqctl clustr_status:查看集群状态

rabbitmqctl change_cluster_node_type disc|ram 修改集群节点的存储形式

rabbitmqctl forget_cluster_node [--offline] 忘记节点(摘除节点)

rabbitmqctl rename_cluster_node oldnode1 newnode1 [oldnode2] [newnode2..] (修改节点名称)

【五】Exchange和路由Key

  • Direct Exchange
    处理路由键。需要将一个队列绑定到交换机上,要求该消息与一个特定的路由键完全匹配。这是一个完整的匹配。
  • Fanout Exchange
    不处理路由键。你只需要简单的将队列绑定到交换机上。一个发送到交换机的消息都会被转发到与该交换机绑定的所有队列上。很像子网广播,每台子网内的主机都获得了一份复制的消息。Fanout交换机转发消息是最快的。
  • topic Exchange
    将路由键和某模式进行匹配。此时队列需要绑定要一个模式上。
    ps: 符号“#”匹配一个或多个词,符号“*”匹配不多不少一个词。

【六】保证信息100%投递成功

  • 第一种开启确认模式:
    开启确认模式以后,当生产端把消息发送MQ后,当消费者消费以后,会返回一个确认消息,以保证消息被消费
  • 第二种消息打标落库:
  • springcloud rabbitmq持久化 rabbitmq持久化缺点_消息队列_03

  • 以订单为例:
    1、当前我们的订单生成成功以后,会保存一份消息在消息数据库中落库。这个时候才会发送消息到MQ中。
    2、当下游消费者去消费后,会再发一个消息到MQ中
    3、上游服务监听这个返回的确认消息,会去把消息数据库中的消息的状态修改为已经消费
    4、分布式的定时任务去查询数据库,当发现了有消息状态为未消费的状态时,会让生产者重新发送消息做补偿机制
  • 第三种消息延迟投递二次确认:
  • springcloud rabbitmq持久化 rabbitmq持久化缺点_消息队列_04

  • 1、生产者发送两条消息,但是第二条消息是延迟投递出去的(2-5分钟)
    2、当下游消费者消费以后,会发送消费完成的消息到MQ
    3、有一个单独的服务区监听队列中的消费完成的消息,当有消息完成的信息时,需要把消息保存到消息数据库中
    4、当单独服务监听到了延迟的消息以后,会去查询数消息据库,看是否有这样的消费完成的信息。如果有则什么都不做。如果没有,就会通知生产者重新发送消息做补偿机制

【七】幂等性

一次和多次请求某一个资源对于资源本身应该具有同样的结果(网络超时等问题除外)。也就是说,其任意多次执行对资源本身所产生的影响均与一次执行的影响相同。

  • 第一种:
    可以借鉴数据库中的悲观锁的机制:
    当我们需要更新一条数据时:
update tableName 
set count = count + 1 ,version = version+1 
where version = 1
  • 第二种:
    唯一id + 指纹码(业务规则) 利用数据库主键去重
  • 第三种:
    利用redis的原子性去重

【八】RabbitMQ的主要作用

  • 异步处理
    场景说明:用户注册后,需要发注册邮件和注册短信
    引入消息队列后,把发送邮件,短信不是必须的业务逻辑异步处理
    由此可以看出,引入消息队列后,用户的响应时间就等于写入数据库的时间+写入消息队列的时间(可以忽略不计),引入消息队列后处理后,响应时间是串行的3倍,是并行的2倍。
  • 应用解耦
    场景:双11是购物狂节,用户下单后,订单系统需要通知库存系统,传统的做法就是订单系统调用库存系统的接口.
    订单系统:用户下单后,订单系统完成持久化处理,将消息写入消息队列,返回用户订单下单成功。
    库存系统:订阅下单的消息,获取下单消息,进行库操作。
    就算库存系统出现故障,消息队列也能保证消息的可靠投递,不会导致消息丢失.
  • 限流削锋
    流量削峰一般在秒杀活动中应用广泛
    场景:秒杀活动,一般会因为流量过大,导致应用挂掉,为了解决这个问题,一般在应用前端加入消息队列。
    作用:
    可以控制活动人数,超过此一定阀值的订单直接丢弃(我为什么秒杀一次都没有成功过呢^^)
    可以缓解短时间的高流量压垮应用(应用程序按自己的最大处理能力获取订单)
    用户的请求,服务器收到之后,首先写入消息队列,加入消息队列长度超过最大值,则直接抛弃用户请求或跳转到错误页面.
    秒杀业务根据消息队列中的请求信息,再做后续处理.