网络上已经有很多人写过各种MQ的性能比较和用法了,我就不再重复说明了。就写一些自己对MQ的理解吧。
为什么要用MQ
MQ的使用场景很多人都可以背得滚瓜烂熟了:业务耗时长,存在并发问题,需要解耦的业务。那么为什么MQ可以解决这些问题呢。首先看看这些场景会带来什么问题。
1. 业务耗时长
比如说我需要创建一条违章订单,这条订单需要先去查找用户绑定车辆信息,会员包信息,再去另一个系统查找车主信息,然后再查找违章信息,再向另一个系统同步下单信息等等20多个步骤,总共需要3秒时间。这3秒时间,是服务器处理一条订单所需要的时间。此时如果有100个用户下单,100单同时卡在这3秒钟内,服务器所有的性能用来处理这堆积的100单,就会造成服务器性能下降,导致处理一单花费的时间更长。假如是5秒,那如果此时再有人下单,就会有更多的订单堵塞在这里。然后性能继续下降,花费的时间更多,死循环了,服务器总得要崩掉。
添加消息中间件,消息中间件可以同时接收万级的请求,并把这些请求存储在消息队列中。下游创建订单的业务花费了3秒,处理完后,消息队列再释放下一个请求过来,这样就变成了请求一个接一个地过来,不会有很多请求堆积在服务器内,造成性能下降。
2. 存在并发问题
比如说我要做一个抢红包系统,用户A和B同时从数据库查找到一个红包,然后A先领取了红包的钱,把红包的状态改为已获取。此时B已经把这个红包查询出来了,再领取红包的钱,如果没有加乐观锁,再次把红包的状态改为已获取,这样就造成了A、B两个人获取到了同一个红包。
如果在这个问题中添加乐观锁,B去修改红包状态的时候就会报错,似乎领取红包的问题就解决了。但如果多人同时抢到红包,就只有第一个人A能够成功领取,其他人都是报错,用户体验就比较差。
添加消息中间件,同样地将这些并发的请求转变为一个接一个的请求,当用户A把红包的领取状态修改完成了,用户B才去获取下一个红包,就不会造成A、B同时获取到同一个红包的情况。
3. 需要解耦的业务
比如说用户购买了会员包之后,需要给用户发送一条手机短信,一条支付宝模版消息。如果把这些流程和下单购买会员包写在一起,如果发送短信失败,购买会员包也会失败。我不希望支付流程会被发送短信流程所影响。
这就是需要解耦的场景,这个时候有两种方式可以选择:1. 创建新线程,单独去执行发短信的流程。2. 使用消息中间件,异步发送短信。这两种方式各有优缺点,视情况选择。
新线程:使用方便,不用额外添加组件。但是无法查看执行状态,如果业务消耗的时间长,同一时间就会有较多的线程被占用。解耦的业务,如果发生改变需要重启,主业务也要重启。
消息中间件:新增加了一个组件,会增加设计上的复杂性,就要多考虑新增组件带来的问题,比如如何使消息百分百发送。同时MQ需要消耗网络资源。好处就是能够查看系统运行状态,解耦的业务发生改变需要重启,可以单独重启而不影响主流程。
简单地说,单工程架构,使用新线程比较好,分布式架构,选择消息中间件。或者选择终极方式:创建一个线程,让这个线程只做一件事——给MQ发消息。