1. 消息系统的价值
1.1没有消息系统的时候
假设你负责系统的用户注册模块开发,突然有一天接到产品的要求让你增加注册成功之后发短信任务,此时你屁颠屁颠的找到用户注册部分的代码,然后你快速的在代码后面加上调用短信服务的代码,心满意足的提交了。又过了几天,心得需求是增加注册送积分活动,然后,呵呵......
1.2引入消息系统
用户注册成功时,发送消息给消息中间件,其他系统向消息中间件订阅这个消息,完成相应工作。通过消息中间件的解耦,注册系统不关心有多少系统需要知道注册成功这件事,也不用关心如何通知它们,只需要把登录成功这件事转化为一个消息发送到消息中间件。这样,需要了解登录成功这件事的系统自己去消息中间件订阅就行。
2. 互联网时代的消息中间件
消息中间件的两个重要特点解耦和异步。需要思考的问题:消息的顺序保证、扩展性、可靠性、业务操作与消息发送的一致性,以及多集群订阅者问题。
2.1消息发送的一致性
异常分析:
- 业务应用发送消息给消息中间件。如果失败,业务操作没有做,消息也没有存储在消息中间件,业务操作和消息的状态是一致的,没有问题。
- 消息中间件把消息入库。如果失败,可能情况:消息中间件失效,应用收不到返回结果;插入消息失败,收到返回失败结果给应用。
- 业务应用收到消息中间件结果异常。如果有业务应用正常,业务应用不知道在消息中间件的处理结果,按照失败来处理,如果入库成功,就会造成不一致;
如果业务应用自身有问题,消息入库成功,也会造成不一致;如果入库失败,则还是一致的。 - 业务应用进行业务操作。
- 业务应用发送业务操作结果给消息中间件。如果出现问题,消息中间件不知道如何操作存储的消息,可能会造成不一致。
- 消息中间件更新消息状态。出现问题同上。
从业务应用的视角分析异常情况:
异常情况 | 可能的状态 |
---|---|
发送消息给消息中间件失败 | 业务操作未进行,消息未存储 |
消息发出后没有收到消息中间件响应 | 业务操作未进行,消息存储,待处理 业务操作未进行,消息未存储 |
收到消息中间件返回成功,业务操作失败 | 业务操作未进行,消息存储,待处理 |
从消息中间件的视角分析异常情况:
异常情况 | 可能的状态 |
---|---|
没有收到业务应用的业务操作结果 | 业务操作未进行,消息存储,待处理 业务操作未进行(操作完又回滚),消息存储,待处理 业务操作成功,消息存储,待处理 |
收到业务应用的业务处理结果,更新消息状态失败 | 业务操作未进行,消息存储,待处理 业务操作未进行(操作完又回滚),消息存储,待处理 业务操作成功,消息存储,待处理 |
各种异常情况状态:
- 业务操作未进行,消息未存储
- 业务操作未进行,消息存储,状态待处理
- 业务操作成功,消息存储,状态待处理
情况1,无需处理,因为本身一致;情况2和情况3需要进行补偿。
最终一致性接口封装伪代码:
- 发送消息给消息中间件
- 获取返回结果
- 如果失败,返回失败
- 进行业务操作
- 获取业务操作结果
- 发送业务操作结果给消息中间件
- 返回处理结果
可以把实现逻辑封装在一个调用中,然后把业务操作包装成一个对象传进来,然后整个流程就可以控制在这个方法中。
2.2消息中间件与使用者的强依赖问题
如果消息中间件系统出现问题,就会导致业务操作无法继续执行。
2.3消息重复投递
- 分布式事务:实现复杂
- 接收者消息处理幂等性:降低消息中间件复杂,增加接受者门槛
2.4消息优先级
局部顺序:和某件事相关的多条消息之间有顺序,创建->付款->发货->确认。
3结束
章节中很多是作者解决问题的思路和实践,所以很多就略过。