RabbitMQ完整复习流程(持续更新····)

RabbitMQ完整复习流程

用户分布式系统之间进行通信;

概念

订单-----将消息放到mq,消费者从mq中拉取;

把mq当作服务器;生产者和消费者当作客户端;

优势

  1. 应用解耦:系统之间交互多;
  2. 异步提速:将数据放到mq之后就可以直接返回;
  3. 消峰填谷:将请求放到mq,系统重mq中获取请求处理;提高系统稳定性;

缺点

系统可用性降低;必须保证mq的高可用;

系统复杂度大大提升;如何保证消息不丢失?

MQ 产品

RabbitMQ简介

基础架构图:

安装使用

  1. 安装erlang 环境

rpm -ivh erlang-18.3-1.el7.centos.x86_64.rpm

  1. 安装rabbitMq

rpm -ivh socat-1.7.3.2-1.1.el7.x86_64.rpm --force --nodeps

rpm -ivh rabbitmq-server-3.6.5-1.noarch.rpm

  1. 开启管理界面
rabbitmq-plugins enable rabbitmq_management

vim /usr/lib/rabbitmq/lib/rabbitmq_server-3.6.5/ebin/rabbit.app # 比如修改密码、配置等等,例如:loopback_users 中的 <<"guest">>,只保 留guest
  1. 启动
service rabbitmq-server start # 启动服务 
service rabbitmq-server stop # 停止服务
service rabbitmq-server restart # 重启服务

工作模式

第二种与第三种的区别:后者可以重复消费;

  • 简单模式:一对一
  • work queue:一对多;
  • 发布订阅:

  • 路由模式:

  • topic通配符模式:

总结

springboot 整合rabbitmq

  1. 导入依赖

  2. 编写yml配置文件,指定基本信息

  3. 定义交换机、队列、以及绑定的关系

  4. 注入RabbitTemplate调用方法完成消息发送

高级特性

  • 消息可靠性投递

消息发送方杜绝消息发送丢失或投递失败;RabbitMq提供了两种模式来解决这个问题;

  1. confirm确认模式: 交换机异常,消息发送不到指定交换机
  2. 退回模式Return:队列异常,通常出现在路由模式或topic模式;数据到达交换机但是没有指定的队列接受该数据;

abbitmq 整个消息投递的路径为:producer—>rabbitmq broker—>exchange—>queue—>consumer
消息从 producer 到 exchange 则会返回一个 confirmCallback 。消息从 exchange–>queue 投递失败则会返回一个 returnCallback 。我们将利用这两个 callback 控制消息的可靠性投递

  • Consumer ACK:消费者确认消息

rabbitmq提供了三种确认消息方法

  1. 手动确认:acknowledge=“manual” 消息到达消费者手中完成相关业务后手动签收,调用channel.basicAck()
  2. 自动确认:acknowledge=“none” 消息一到消费者手中就自动签收;
  3. 根据异常情况确认:acknowledge=“auto”

消息拒绝签收问题:就像包裹拒绝签收一样,到底是退回还是丢弃?

channel.basicNack("消息id","","是否重新放回队列")

  • 消费端限流

消息必须手动确认;

配置prefetch每次抓取多少消息;

  • TTL:配置过期时间
  1. 当消息到达存活时间后,还没有被消费,会被自动清除
  2. RabbitMQ可以对消息设置过期时间,也可以对整个队列(Queue)设置过期时间

  1. 设置队列过期时间使用参数:x-message-ttl,单位:ms(毫秒),会对整个队列消息统一过期。
  2. 设置消息过期时间使用参数:expiration。单位:ms(毫秒),当该消息在队列头部时(消费时),会单独判断这一消息是否过期。
  3. 如果两者都进行了设置,以时间短的为准。
  • 死信队列DLX:当消息成为dead message后,会发送到另一个交换机;叫做DLX(Dead Letter Exchange)

为什么会有死信

  1. 队列消息长度到达限制;
  2. 消费者拒接消费消息,basicNack/basicReject,并且不把消息重新放入原目标队列,requeue=false;
  3. 原队列存在消息过期设置,消息到达超时时间未被消费;

消息存放在队列中,那么就需要为消息绑定死信队列;给队列设置参数: x-dead-letter-exchangex-dead-letter-routing-key

其中死信队列和死信交换机没有区别;消息成为死信后会被重新路由到配置好的DLX,DLX再路由到死信队列;

  • 延迟队列:消息到到队列后不会被立马消费,而是到指定时间后才会被消费;

打个比方:1. 下单后,30分钟未支付,取消订单,回滚库存。 2.新用户注册成功7天后,发送短信问候。

如何实现? TTL + 延迟队列

但是!RabbitMQ 并没有提供延迟队列功能;所以就只能使用ttl+死信队列来实现了!

思路;过期的消息会放到死信队列;那么只要创建消费者监听死信队列中的消息即可;死信队列中出现消息就会被消费,就能巧妙的实现延迟队列的效果!

  • 消息幂等性: 乐观锁

    幂等性指一次和多次请求某一个资源,对于资源本身应该具有同样的结果。也就是说,其任意多次执行对资源本身所产生的影响均与一次执行的影响相同。 在MQ中指,消费多条相同的消息,得到与消费该消息一次相同的结果。

如何防止消息重复消费,消息积压

  • 消息积压:
  1. 消费者宕机积压
  2. 消费者消费能力不足积压
  3. 发送者发流量太大

解决方案:上线更多的消费者,进行正常消费;

上线专门的队列消费服务,将消息先批量取出来,记录数据库,再慢慢处理

RabbitMQ如何保证消息顺序性

比方现在有三条消息:插入,更新,删除;

将这三条消息发送到消息队列,如何才能保证消息的顺序呢?

首先可以确定的是,多个消费者肯定不行,会出问题,那就简单点,

  • 使用一个消费者消费同一个队列就行;

这样就ok了嘛?并不是 ;如果该消费者里面进行多线程操作的话,依旧保证不了顺序;

所以:需要明确两个点:

  1. 队列中的消息必须有序
  2. 消费者获取的消息必须有序;

第一点不用考虑,因为消息的推送本来就是有序的,所以不需要考虑它,只需要将问题在消费这消费这里解决就行;

消费者要想保证顺序,就得保证拿到的消息是有顺序的,也就是消费者只能上一个队列里面拿消息;拿到消息之后本身也得按照顺序执行,也就是顺不同异步,只能同步,处理完一条后在处理下一条,这样就能完美解决了!

可是这样会产生一个问题:这样岂不是需要很多队列?也就是需要很多消费者?如何解决这种问题?

其实也简单,不希望产生多个队列,那就只用一个队列呗;反正队列里面的消息始终都是有序的,我们只需要保证消费者拿到的消息有序就行,那这样就只有一个消费者,我们可以将获取到的消息在消费者内部进行排序不就好了;将具有同样属性的消息放到一个list集合里面(比如对同一条记录操作,那他们的主键ID必然是一样的);这样产生不同的list,在将这些list分发给不同的work执行不就好了;

执行思考就会发现,第二种方式无非就是把消费者又当成了生产者,将消息进行过滤后放到list集合,然后又启用不同的消费者来消费罢了,换汤不换药!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值