主要作用
消息队列的主要作用,有解耦,异步,消峰
解耦
将消息写入消息队列,需要消息的系统自己从消息队列中订阅,从而系统不需要做任何修改。
异步
将消息写入消息队列,非必要的业务逻辑以异步的方式运行,加快响应速度
削峰
系统慢慢的按照数据库能处理的并发量,从消息队列中慢慢拉取消息。在生产中,这个短暂的高峰期积压是允许的
一个小栗子
拿某宝的“运动”项目举例,它每天记录你的步数,比如3000步。这时候 “种树”项目来了,希望通过的你步数,看你是否进行了环保运动,如果运动达标,则产生对应的奖励(比如可以让你的树更好的生长)。又过了一段时间,一个新的项目产生了,它也希望通过步数来达到一个目的,比如通过你的步数,可以模拟在线运动,比如通过累计步数,通过计算多少步,来展示你绕地球几圈。 我们分别标记 运动项目为A,种树项目为B,模拟在线运动项目为C
结构如下图
我们发现,每当有相关子系统接入希望获取到A产生的步数的时候,A系统必定要修改代码去发起调用对应子系统去通知其完成业务。那有什么更好的办法呢?
设计模式中,观察者模式是一个很好的解耦的反感,A产生数据,然后去批量通知监听者去发起业务。B和C分别作为监听者,当接收到通知时自主去进行相关业务操作。 但是再思考一下A要处理的事情。
1)产生数据(0.7s)
2)通知被监听者B和C发起业务(0.032s + 0.032s)
这里我思考有个问题,第一个当产生数据后第二步的时间是随着被监听者的增多而增加的,如果数量过多,会对A系统自身的业务执行造成影响,比如用户体验度下降。如果将第二步操作改为异步线程去执行呢,当第一步操作完成后,异步通知第二步去操作通知各个监听者。这样做是可以解决问题,但是考虑到A系统自身线程池资源的消耗,以及多个雷同A系统的业务发生时,我们是否都需要去考虑这么一套模式去实现呢,有没有一个东西,我们去通知它,然后它来帮我们合理的完成这么一个工作呢。此时,我们的消息中间件就登场了。
这时候A系统的执行过程就变成
1)产生数据(0.7s)
2)发送数据给消息队列(0.045s)
这个时候我们A系统的过程执行时间就可预估了,并且也无需再考虑其他系统的执行过程了。
上例是别人看了某宝后的自己的假想实现方式,并未真正了解某宝,请勿作准,只是为了阐述自己的观点
缺点
当然,使用了消息队列,也会产生对应的一些问题
- 系统可用性降低
任何系统都有宕机的风险,所以要考虑MQ中间件不稳定情况,做好集群和灾备是必须的 - 系统复杂性增加
需要考虑其他更多影响系统因素,比如一致性问题,消息的重复消费等
常用的消息队列
当然,综上所诉的一切,并不需要我们去实现它,我们已经有一些开源的MQ中间件供我们选用
- activemq
- rabbitmq
- rocketmq
- kafka
- …