CS-Notes/docs/notes/消息队列.md

87 lines
4.1 KiB
Java
Raw Normal View History

2019-11-02 14:39:13 +08:00
<!-- GFM-TOC -->
* [消息模型](#一消息模型)
* [点对点](#点对点)
* [发布/订阅](#发布订阅)
* [使用场景](#二使用场景)
* [异步处理](#异步处理)
* [流量削锋](#流量削锋)
* [应用解耦](#应用解耦)
* [可靠性](#三可靠性)
* [发送端的可靠性](#发送端的可靠性)
* [接收端的可靠性](#接收端的可靠性)
* [参考资料](#参考资料)
<!-- GFM-TOC -->
2019-03-27 20:57:37 +08:00
# 消息模型
## 点对点
2018-08-07 17:52:24 +08:00
消息生产者向消息队列中发送了一个消息之后只能被一个消费者消费一次
2019-12-12 01:20:12 +08:00
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/image-20191212011250613.png"/> </div><br>
2018-08-07 17:52:24 +08:00
2019-03-27 20:57:37 +08:00
## 发布/订阅
2018-08-07 17:52:24 +08:00
消息生产者向频道发送一个消息之后多个消费者可以从该频道订阅到这条消息并消费
2019-12-12 01:20:12 +08:00
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/image-20191212011410374.png"/> </div><br>
2018-08-07 17:52:24 +08:00
发布与订阅模式和观察者模式有以下不同
2019-04-27 12:22:25 +08:00
- 观察者模式中观察者和主题都知道对方的存在而在发布与订阅模式中生产者与消费者不知道对方的存在它们之间通过频道进行通信
- 观察者模式是同步的当事件触发时主题会调用观察者的方法然后等待方法返回而发布与订阅模式是异步的生产者向频道发送一个消息之后就不需要关心消费者何时去订阅这个消息可以立即返回
2018-08-07 17:52:24 +08:00
2019-12-12 01:20:12 +08:00
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/image-20191212011747967.png"/> </div><br>
2018-08-07 17:52:24 +08:00
2019-03-27 20:57:37 +08:00
# 使用场景
2018-08-07 17:52:24 +08:00
2019-03-27 20:57:37 +08:00
## 异步处理
2018-08-07 17:52:24 +08:00
发送者将消息发送给消息队列之后不需要同步等待消息接收者处理完毕而是立即返回进行其它操作消息接收者从消息队列中订阅消息之后异步处理
2018-09-01 01:22:24 +08:00
例如在注册流程中通常需要发送验证邮件来确保注册用户身份的合法性可以使用消息队列使发送验证邮件的操作异步处理用户在填写完注册信息之后就可以完成注册而将发送验证邮件这一消息发送到消息队列中
2018-08-07 17:52:24 +08:00
只有在业务流程允许异步处理的情况下才能这么做例如上面的注册流程中如果要求用户对验证邮件进行点击之后才能完成注册的话就不能再使用消息队列
2019-03-27 20:57:37 +08:00
## 流量削锋
2018-08-07 17:52:24 +08:00
在高并发的场景下如果短时间有大量的请求到达会压垮服务器
可以将请求发送到消息队列中服务器按照其处理能力从消息队列中订阅消息进行处理
2019-03-27 20:57:37 +08:00
## 应用解耦
2018-08-07 17:52:24 +08:00
如果模块之间不直接进行调用模块之间耦合度就会很低那么修改一个模块或者新增一个模块对其它模块的影响会很小从而实现可扩展性
通过使用消息队列一个模块只需要向消息队列中发送消息其它模块可以选择性地从消息队列中订阅消息从而完成调用
2019-03-27 20:57:37 +08:00
# 可靠性
2018-08-07 17:52:24 +08:00
2019-03-27 20:57:37 +08:00
## 发送端的可靠性
2018-08-07 17:52:24 +08:00
发送端完成操作后一定能将消息成功发送到消息队列中
2019-04-27 12:22:25 +08:00
实现方法在本地数据库建一张消息表将消息数据与业务数据保存在同一数据库实例里这样就可以利用本地数据库的事务机制事务提交成功后将消息表中的消息转移到消息队列中若转移消息成功则删除消息表中的数据否则继续重传
2018-08-07 17:52:24 +08:00
2019-03-27 20:57:37 +08:00
## 接收端的可靠性
2018-08-07 17:52:24 +08:00
2018-08-13 14:47:06 +08:00
接收端能够从消息队列成功消费一次消息
2018-08-07 17:52:24 +08:00
2018-09-03 22:34:58 +08:00
两种实现方法
2018-08-07 17:52:24 +08:00
2019-03-27 20:57:37 +08:00
- 保证接收端处理消息的业务逻辑具有幂等性只要具有幂等性那么消费多少次消息最后处理的结果都是一样的
- 保证消息具有唯一编号并使用一张日志表来记录已经消费的消息编号
# 参考资料
- [Observer vs Pub-Sub](http://developers-club.com/posts/270339/)
- [消息队列中点对点与发布订阅区别](https://blog.csdn.net/lizhitao/article/details/47723105)
2019-11-02 14:39:13 +08:00
2019-11-02 17:33:10 +08:00
<div align="center"><img width="320px" src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/githubio/公众号二维码-2.png"></img></div>