RabbitMQ
网课链接 https://www.bilibili.com/video/BV1cb4y1o7zz?from=search&seid=14532494014117853629&spm_id_from=333.337.0.0
相关链接 https://blog.csdn.net/lyyrhf/article/details/120159288
相关代码 https://gitee.com/userwhz/rabbitmq-ssg
入门
MQ
队列 存放message
跨进程
作用
流量削峰 做缓冲
应用解耦 中间件
异步处理 无需等待
分类
Active MQ
优点 单机吞吐量万级 时效性ms级 可靠性高 基于主从架构
缺点 社区资源少
Kafka
优点 百万级TPS 分布式 成熟管理界面和日志 实时计算和日志采集
缺点 不支持重试 社区更新慢
RocketMQ
优点 十万级 0丢失 支持10亿级别的消息堆积
缺点 支持的客户端语言不多 社区活跃度不高
RabbitMQ
优点 万级 支持多种语言 社区活跃度高
缺点 商业版需要收费
选择
Kafka 大量数据 日志采集
RocketMQ 金融互联网
RabbitMQ 时效性微秒级 数据量不高 界面使用简单
工作流程
接收存储转发消息
交换机 队列 绑定关系
可以一对多
队列 消费者
一对一
工作原理
Producer Connection(Channnel) Broker(Exchange(Queue)) Connection(Channnel) Consumer
一次TCP 多个信道
安装
常用命令
chkconfig rabbitmq-server on 添加开机启动RabbitMQ服务
/sbin/service rabbitmq-server start 启动服务
/sbin/service rabbitmq-server status 查看服务状态
后台管理界面
rabbitmq-plugins enable rabbitmq_management 开启web管理插件 需要先关闭服务
/sbin/service rabbitmq-server stop 关闭服务
访问网站 端口号15672
rabbitmqctl add_user admin 123 创建账号
rabbitmqctl set_user_tags admin administrator 添加用户角色
设置用户权限
set_permissions [-p <vhostpath>] <user> <conf> <write> <read>
rabbitmqctl set_permissions -p "/" admin ".*" ".*" ".*"
查看用户和角色
rabbitmqctl list_users
核心部分
Hello World
简单模式
Java开发环境搭建
channel.queueDeclare(name, durable, autoDelete, exclusive, noWait, args)
ctrl + p 查看方法参数
需要开启5672端口
一个生产者 一个队列 一个消费者
Work queues
工作模式
一个生产者 大量消息 一个队列 多个工作线程(消费者)
原则 生成者发送的消息只能被处理一次
轮询分发
消费者 启动多个线程
消息丢失
处理消息过程中发生类似宕机情况
消息应答
返回处理结果
分类
自动应答 不太靠谱 以接收到消息为主
手动应答
basicAcl 肯定确认 成功处理,可以丢弃
basicNack 否定确认
basicReject 否定确认 相比basicNack少了一个参数(是否批量处理) 不处理该消息直接拒绝,可以将其丢弃
手动优点
可以批量处理 并且减少网络拥堵
一般不批量处理 批量处理可能造成消息的丢失
消息自动重新入队
持久化
队列持久化
生产者 声明队列时参数设置即可
消息持久化
生产者 修改channel.basicPublish参数
不公平分发
消费方设置
perfetchCount = 1
channel.basicQos(1)
预取值
能力达到什么程度?
指定分配的消息树
prefetch 默认1 即产生轮询
perfetchCount = 2 .. 表示预取值
Publisher Confirms
发布确认模式
生产者设置队列持久化 消息持久化 仍然可能丢失
发布确认 确认消息已经保存在磁盘上持久化了
开启发布确认的方法
channel.confirmSelect();
类别
单个发布确认 同步确认 缺点 吞吐量低
批量发布确认 缺点 当发生故障导致发布出现问题时,不知道是哪个消息出现问题
异步确认 监听器监听 消息编号 利用回调函数来达到消息可靠性传递 实现稍难
异步未确认消息的处理
用ConcurrentLinkedQueue这个队列在confirm callbacks与发布线程之间进行消息的传递
Publish/Subscribe
发布订阅模式
交换机(Exchanges)
消息被消费两次
交换机将消息转发给两个队列
类型
直接(direct)路由类型
主题(topic)
标题(headers)
扇出(fanout)发布订阅模式 将消息发布到它的队列中
无名exchange
默认类型
临时队列
不带有持久化的队列
binding
交换机通过RoutingKey确认发送给哪一个队列
Routing
路由模式
direct交换机
RouyingKey一样订阅模式
不一样就是路由模式
Topics
主题模式
routing_key需要满足一定的要求
*代表一个单词
#代表多个单词
高级部分
死信队列
死信 无法被消费的消息
例
消费发生异常
商品下单成功后未支付
来源
消息TTL过期
队列达到最大长度
消息被拒绝(basic.reject或basic.nack 且requeue=false)
延迟队列
死信队列的一种
消息的TTL过期就是延迟队列
内部有序
作用
定时任务
整合springboot
实现 普通实现
优化 实现通用延迟队列
用插件实现 基于死信 只检测第一消息 可能忽略第二个消息 可以实现交换机延迟
延时队列在需要延时处理的场景下非常有用,使用RabbitMQ来实现延时队列可以很好的利用RabbitMQ.的特性,如:消息可靠发送、消息
可靠投递、死信队列来保障消息至少被消费一次以及未被正确处理的消息不会被丢弃。另外,通过RabbitMQ集群的特性,可以很好的解
决单点故障问题,不会因为单个节点挂掉导致延时队列不可用或者消息丢失。当然,延时队列还有很多其它选择,比如利用Java的
DelayQueue,利用Redis的zsset,利用Quartz或者利用kafka的时间轮,这些方式各有特点,看需要适用的场景
发布确认高级
发布确认
springboot
服务器宕机 导致消息丢失
通过缓存进行重新投递
回退消息
在仅开启了生产者确认机制的情况下,交换机接收到消息后,会直接给消息生产者发送确认消息,如果发现该消息不可路由,那么消息会
被直接丢弃,此时生产者是不知道消息被丢弃这个事件的。通过设置mandatory参数可以在当消息传递过程中不可达目的地时将消息返回
给生产者。
备份交换机
备份交换机可以理解为 RabbitMQ 中交换机的“备胎”,当我们为某一个交换机声明一个对应的备份交换机时,就是为它创建一个备胎,当
交换机接收到一条不可路由消息时,将会把这条消息转发到备份交换机中,由备份交换机来进行转发和处理,通常备份交换机的类型为
Fanout ,这样就能把所有消息都投递到与其绑定的队列中,然后我们在备份交换机下绑定一个队列,这样所有那些原交换机无法被路由
的消息,就会都进入这个队列了。当然,我们还可以建立一个报警队列,用独立的消费者来进行监测和报警。
幂等性
用户对于同一操作发起的一次请求或者多次请求的结果是一致的,不会因为多次点击而产生了副作用
消息被重复消费
MQ消费者的幂等性的解决一般使用全局ID或者写个唯一标识比如时间戳或者UUID或者订单消费者消费MQ中的消息也可利用MQ的该id
来判断,或者可按自己的规则生成一个全局唯一id,每次消费消息时用该id先判断该消息是否已消费过。
业界主流的幂等性有两种操作
a.唯一ID+指纹码机制,利用数据库主键去重,
b.利用redis.的原子性去实现
唯一ID+指纹码机制
指纹码:我们的一些规则或者时间戳加别的服务给到的唯一信息码,它并不一定是我们系统生成的,基本都是由我们的业务规则拼接而来,
但是一定要保证唯一性,然后就利用查询语句进行判断这个id是否存在数据库中,优势就是实现简单就一个拼接,然后查询判断是否重复;
劣势就是在高并发时,如果是单个数据库就会有写入性能瓶颈当然也可以采用分库分表提升性能,但也不是我们最推荐的方式
Redis原子性
利用redis执行setnx命令,天然具有幂等性,从而实现不重复消费
优先队列
设置优先级
官方允许是0-255之间,此处设置10,允许优化级范围为0-10,不要设置过大,浪费CPU与内存
惰性队列
正常情况下:消息保存在内存中
惰性队列:消息保存在磁盘中
使用情况
费者宕机 消息堆积
性能低
集群部分
搭建集群
镜像队列
集群不可复用 单台机器宕机导致队列丢失
如果RabbitMQ集群中只有一个Broker节点,那么该节点的失效将导致整体服务的临时性不可用,并且也可能会导致消息的丢失。可以将
所有消息都设置为持久化,并且对应队列的durable属性也设置为true,但是这样仍然无法避免由于缓存导致的问题:因为消息在发送之后和
被写入磁盘井执行刷盘动作之间存在一个短暂却会产生问题的时间窗。通过publisherconfirm机制能够确保客户端知道哪些消息己经存入
磁盘,尽管如此,一般不希望遇到因单点故障导致的服务不可用
引入镜像队列(Mirror Queue)的机制,可以将队列镜像到集群中的其他Broker节点之上,如果集群中的一个节点失效了,队列能自动
地切换到镜像中的另一个节点上以保证服务的可用性。
实现高可用负载均衡
通过HAProxy + keepalived实现
Federation Exchange
通过交换机实现数据同步
Fedeation Queue
联邦队列可以在多个 Broker 节点(或者集群)之间为单个队列提供均衡负载的功能。一个联邦队列可以连接一个或者多个上游队列(upstream
queue),并从这些上游队列中获取消息以满足本地消费者消费消息的需求
Shovel
数据转发备份
源端数据转发到目的地
负责连接源和目的地、负责消息的读写及负责连接失败问题的处理