概述
消息队列中间件是分布式系统中重要的组件,主要解决应用解耦,异步消息,流量削峰等问题,实现高性能,高可用,可伸缩和最终一致性架构,是大型分布式系统不可缺少的环节.
应用场景
异步处理
用户注册时,一般需要进行注册信息写入数据库,发送注册邮件和发送注册成功短信三个操作,处理方式有三种:
- 串行方式
将注册信息写入数据库后,发送注册邮件,发送注册成功短信,三个操作全部完成后再返回客户端,如下图:
- 并行方式
将注册信息写入数据库后,发送邮件的同时发送注册成功短信,三个操作完成后再返回客户端,如下图:
- 引入消息队列
将不是必须的业务操作放入消息队列进行异步处理
假设三个业务执行时间都是50毫秒,不考虑其他操作业务开销,则串行方式执行时间是150ms,并行方式执行时间是100ms,引入消息队列后执行时间仅需50ms,据此计算出串行方式1秒可处理请求数不到7次(1000/150),并行是10次(1000/100),而消息队列方式可执行20从(1000/20).
应用解耦
用户下单后,订单系统需要通知库存系统,这里有两种做法:
- 传统方式
订单系统直接调用库存系统接口,成功后返回客户端
- 引入消息队列
订单系统:用户下单后,订单系统完成持久化操作后将消息写入消息队列,立即返回客户端
库存系统:订阅下单消息,采用拉/推方式获取下单信息进行库存操作
可以比对得出,传统方式有两个弊端:
- 库存系统一旦出现异常,则减库存操作会失败,进而导致订单失败
- 订单系统与库存系统耦合
引入消息队列后,订单系统写入消息队列后即不再关心后续操作,实现订单系统与库存系统的解耦,并且库存系统异常也不会影响订单系统.此方式也提高了扩展性,如果需要添加一个消息后续处理系统,仅仅只需要这个系统订阅消息队列即可.
流量削峰
流量削峰经常用于秒杀活动当中,此类活动一般瞬时流量特别大,严重会导致服务挂掉,这里有两种处理方式:
- 增加服务器
这种方式简单快速高效,但缺点是活动每次就一会,其余时间服务器一直是闲置的,因而不可取
- 引入消息队列
服务器接收到用户的请求后,首先写入消息队列,如果消息队列长度超过最大数量,则抛弃用户请求或跳转到错误页面,而秒杀系统则根据消息队列中的数据做后续处理.
这种方式有两个优点
- 可以控制参与活动的人数
- 可以缓解短时间内高流量压垮服务器
日志处理
日志处理是指引入消息队列(比如Kafka),解决大量日志传输的问题,具体如下:
- 日志采集客户端负责采集日志,并将消息写入消息队列系统
- 消息队列负责日志数据的接收,存储和转发
- 日志处理系统负责订阅并消费消息队列中的日志
消息通讯
消息队列一般都内置高效通信系统,因而可以应用在消息通讯,比如点对点通讯,聊天室等.
- 点对点通讯
客户端A和客户端B使用同一队列,进行消息通讯
- 聊天室
客户端A,客户端B,客户端N订阅同一主题,进行消息发布和接收,实现类似聊天室效果
应用实例
电商系统
消息队列采用高可用,可持久化的消息中间件,比如Active MQ,Rabbit MQ,Rocket MQ等.
- 应用完成主业务后,将信息写入消息队列,开启消息的确认模式来确定消息是否发送成功
- 扩展流程订阅消息,采用推或拉方式获取并处理消息
- 消息队列解耦应用的同时带来了数据一致性的问题,可采用最终一致性方式解决
日志收集系统
- Zookeeper提出负载均衡和地址查找服务
- 日志收集客户端用于采集日志并将消息推送到Kafka队列
- Kafka集群负责接收,路由,存储,转发消息处理
- Storm集群及OtherApp采用拉的方式消费消息队列的数据