【大白话系列】-- 消息队列MQ

【大白话系列】-- 消息队列

一、为什么使用消息队列?

解耦异步削峰

一个主流的电商系统,一个完整的下单流程包括:下单支付优惠券积分短信等等流程。这么长的链路不可能顺序执行,这样效率太低,所以我们需要同时做。所以最常用的方法:异步

1.1 异步

如1.2 中的图,当下单的流程完成,其他比如优惠券、积分等同步进行,这样大大节省了时间。

1.2 解耦

说到异步,首先最简单的方法就是使用线程去实现。一个业务就调用一个接口,但是每次加一个你要调用一个接口然后还要重新发布系统,这样非常不便。而且系统耦合非常严重,出问题难排查等等问题。

如果用到消息队列,当下单了,就把支付成功的消息告诉别的系统。我只用走完自己的流程,把消息发出去,其他系统订阅我发出去的支付成功的消息。

 

那么出现一个问题,我的下单流程走完了,我不用管别人是否成功吗?比如我下单了积分没增加,优惠券没扣等等,怎么办?

这其实是用了消息队列的一个缺点,涉及到分布式事务的知识点,后面会说到。这也告诉我们,任何技术都是有利有弊的,我们要懂得取舍。

1.3 削峰

拿比较常见的秒杀系统为例,平时流量较低,但是到了秒杀时间,比如00:00的时候,流量一下暴增,这时候服务器,Redis,MySQL各自的承受能力不一样,某个被击垮后容易引起服务雪崩

我们可以把请求放入队列中,根据自己服务器的能力去决定每秒消费多少请求,这样可能比平时慢一点,但这样能保证服务器的稳定性,不至于一下把服务器击垮。在生产中,这个短暂的高峰期积压是允许的。

二、技术是把双刃剑

它给我们带来便利的同时,产生的问题也接踵而至。主要从三个方面介绍其缺点:

2.1 可用性

本来其他系统只要运行好好的,那你的系统就是正常的。

加入MQ之前不用考虑消息丢失、MQ挂掉等问题,但是,引入MQ之后你就需要去考虑了!因此,系统可用性降低

2.2 复杂性

要多考虑很多方面的问题,比如一致性问题、如何保证消息不被重复消费,如何保证保证消息可靠传输。

因此,需要考虑的东西更多,系统复杂性增大。

2.3 一致性问题

消息队列可以实现异步,消息队列带来的异步确实可以提高系统响应速度。但是,万一消息的真正消费者并没有正确消费消息怎么办?比如前面说的,积分没有增加等等情况,这样就会导致数据不一致的情况了!

 

三、重复消费

3.1 为什么造成重复消费

无论是那种消息队列,造成重复消费原因其实都是类似的。正常情况下,消费者在消费消息时候,消费完毕后,会发送一个确认信息给消息队列,消息队列就知道该消息被消费了,就会将该消息从消息队列中删除。只是不同的消息队列发送的确认信息形式不同。kafka有个offset的概念,当每个消息被写进去后,都有一个offset,代表他的序号,然后consumer消费该数据之后,隔一段时间,会把自己消费过的消息的offset提交一下,代表已经消费过了。

但是因为网络传输等等故障,确认信息没有传送到消息队列,导致消息队列不知道自己已经消费过该消息了,再次将该消息分发给其他的消费者。

3.2 如何解决

针对这种问题,我们需要从业务角度,考虑它的幂等性。幂等:执行次数和执行结果没有直接关系,通俗了讲就是你同样的参数调用我这个接口,调用多少次结果都是一样。

怎么保证消息队列消费的幂等性?

我们需要结合业务来思考,比如下面的例子:

  1. 比如某个数据要写库,你先根据主键查一下,如果数据有了,就别插入了,update一下好吧

  2. 比如你是写redis,那没问题了,反正每次都是set,天然幂等性

  3. 如果上面两种都不行,我们就利用第三方介质,对于消息,我们可以建个表(专门存储消息消费记录),然后每次都去查询。

 

四、顺序消费

3.1 为什么需要顺序消费

比如一个电商的下单操作,下单后先减库存然后生成订单,这个操作就需要顺序执行。

再比如数据库同时对一个Id的数据进行了增、改、删三个操作,但是你消息发过去消费的时候变成了改,删、增,这样数据就不对了。

3.2 如何解决

  1. 首先生产者需要保证入队的顺序,入队都是乱的那再厉害的MQ也没有办法。

  2. 一般的MQ都能保证内部消息队列是FIFO的(先进先出),但是只是针对一个消息队列中(kafka中就是partition,rabbitMq中就是queue),所以在发送消息的时候可以使用Hash取模法将同一个操作的消息发送到同一个消息队列里面,这样就能保证出队时是顺序的了。

  3. 消费者也需要注意,如果多个消费者同时消费一个队列。一样可能出现顺序错乱的情况。这就相当于是多线程消费了!

 

五、数据丢失

生产者弄丢数据

消息队列弄丢数据

消费者弄丢数据

六、分布式事务

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值