目录
什么是消息队列?
区别于CS架构下,客户端发出请求,服务器处理请求,发回响应的同步模式,
消息队列则通过引入一个存放请求的中间层,来实现异步处理请求的模式,在某些场景下很有用
优点
- 业务解耦:
比如说,
下订单要修改库存,订单系统需要调用库存系统的接口,如果库存系统出问题则会影响订单系统,
用消息队列可以持久化订单消息,等库存系统恢复后再取消息处理
再比如
系统A依赖于系统B、C,调用它们的接口传递数据,现在想引入系统D,就得改代码了,用消息队列可以解耦,需要数据的自行去取
我有一个日志系统,会将记录的日志写入硬盘、打印到屏幕,现在我想加一个日志分析,就得修改代码,调用接口
而用消息队列的话,把日志扔到队列里,需要的系统自己去取,还能通过路由实现不同级别的日志统计
- 异步:把任务打包放到队列里,不用立刻处理任务,等到空闲时再取出进行处理,或让后台线程进行处理
- 削峰:高并发流量时,避免冲垮服务器,将请求打包成消息暂放到队列里,服务器可以根据处理能力从队列拉取请求来处理
- 存储:将请求打包成消息进行持久化,避免服务进程挂掉消息丢失,等重启后再取出消息进行处理
缺点
- 可用性降低:引入了新的组件,消息队列挂掉时影响系统可用性
- 复杂性变强:需要考虑一些新的问题,如
- 如何避免消息重复消费?
- 消息丢失?
- 一致性(异步处理任务)
应用场景
- 高并发流量削峰
- 异步处理任务(如 验证码短信)
- 日志
- 业务解耦
RabbitMQ的组件
- 生产者:消息发送方
- 消费者:消息接收方
- 队列:消息的存储、缓冲区
- 消息:内容+路由键(消息的标签,用来判断应该投放到哪个队列)
- 交换器:转发消息到队列
- 绑定:依据绑定键来关联队列和交换器,从而使得交换器能认识队列,以后能往那投消息
- 连接:到RabbitMQ服务器的socket连接
- 信道:连接中的消息收发通道,一个连接可以有多个信道
工作流程
消息传递的过程可以形象地用邮递信件来做比喻,
消息是邮件,路由键相当于邮件接收地址,队列是邮箱,交换器就是邮递员,绑定就是给邮递员指派负责哪些邮箱的投递,
连接是到邮局的路,信道是邮局的一个服务窗口
发送消息的过程:
建立连接--得先有一条家门到邮局的路
建立信道--得占到一个服务窗口
声明交换器--指定邮递员
发送消息,指定路由键、交换器--往信上写地址,交给邮递员
消息投递的过程:
依据绑定键绑定队列和交换器:给邮递员指派负责投递哪些邮箱
邮递员有不同性格,
A:抄信,往自己管的每个邮箱里都塞一份
B:把信塞到信上指定的邮箱里
C:信上地址写得不清楚,觉得可能对的邮箱都塞一份
D
消息接收的过程
建立连接--得先有一条家门到邮局的路
建立信道--得占到一个服务窗口
订阅队列--登记自己想从哪个邮箱接收邮件
注册回调函数来消费消息--有邮件时打电话通知自己
6种模式
- 路由:精确匹配路由键
- 通配符:模糊匹配路由键
- 发布-订阅:不匹配
- headers:根据消息中的headers属性匹配
防止重复消费?保证任务会被消费?
- 防止重复消费:
- 操作幂等
- 消息带上唯一id,消费者可以去重
- 保证任务会被消费:
- 等消费者确认才删除
- 超时重传