MQ相关总结

为什么使用消息队列

先说一下消息队列常见的使用场景吧,其实场景有很多,但是比较核心的有 3 个:解耦、异步、削峰。

解耦

看这么个场景。A 系统发送数据到 BCD 三个系统,通过接口调用发送。如果 E 系统也要这个数据呢?那如果 C 系统现在不需要了呢?A 系统负责人几乎崩溃…
在这里插入图片描述
在这个场景中,A 系统跟其它各种乱七八糟的系统严重耦合,A 系统产生一条比较关键的数据,很多系统都需要 A 系统将这个数据发送过来。A 系统要时时刻刻考虑 BCDE 四个系统如果挂了该咋办?要不要重发,要不要把消息存起来?头发都白了啊!

如果使用 MQ,A 系统产生一条数据,发送到 MQ 里面去,哪个系统需要数据自己去 MQ 里面消费。如果新系统需要数据,直接从 MQ 里消费即可;如果某个系统不需要这条数据了,就取消对 MQ 消息的消费即可。这样下来,A 系统压根儿不需要去考虑要给谁发送数据,不需要维护这个代码,也不需要考虑人家是否调用成功、失败超时等情况。
在这里插入图片描述
总结: 通过一个 MQ,Pub/Sub 发布订阅消息这么一个模型,A 系统就跟其它系统彻底解耦了。

异步

再来看一个场景,A 系统接收一个请求,需要在自己本地写库,还需要在 BCD 三个系统写库,自己本地写库要 3ms,BCD 三个系统分别写库要 300ms、450ms、200ms。最终请求总延时是 3 + 300 + 450 + 200 = 953ms,接近 1s,用户感觉搞个什么东西,慢死了慢死了。用户通过浏览器发起请求,等待个 1s,这几乎是不可接受的。
在这里插入图片描述
一般互联网类的企业,对于用户直接的操作,一般要求是每个请求都必须在 200 ms 以内完成,对用户几乎是无感知的。
在这里插入图片描述
如果使用 MQ,那么 A 系统连续发送 3 条消息到 MQ 队列中,假如耗时 5ms,A 系统从接受一个请求到返回响应给用户,总时长是 3 + 5 = 8ms,对于用户而言,其实感觉上就是点个按钮,8ms 以后就直接返回了,爽!网站做得真好,真快!

削峰

每天 0:00 到 12:00,A 系统风平浪静,每秒并发请求数量就 50 个。结果每次一到 12:00 ~ 13:00 ,每秒并发请求数量突然会暴增到 5k+ 条。但是系统是直接基于 MySQL 的,大量的请求涌入 MySQL,每秒钟对 MySQL 执行约 5k 条 SQL。
一般的 MySQL,扛到每秒 2k 个请求就差不多了,如果每秒请求到 5k 的话,可能就直接把 MySQL 给打死了,导致系统崩溃,用户也就没法再使用系统了。
但是高峰期一过,到了下午的时候,就成了低峰期,可能也就 1w 的用户同时在网站上操作,每秒中的请求数量可能也就 50 个请求,对整个系统几乎没有任何的压力。
在这里插入图片描述
如果使用 MQ,每秒 5k 个请求写入 MQ,A 系统每秒钟最多处理 2k 个请求,因为 MySQL 每秒钟最多处理 2k 个。A 系统从 MQ 中慢慢拉取请求,每秒钟就拉取 2k 个请求,不要超过自己每秒能处理的最大请求数量就 ok,这样下来,哪怕是高峰期的时候,A 系统也绝对不会挂掉。而 MQ 每秒钟 5k 个请求进来,就 2k 个请求出去,结果就导致在中午高峰期(1 个小时),可能有几十万甚至几百万的请求积压在 MQ 中。
在这里插入图片描述
这个短暂的高峰期积压是 ok 的,因为高峰期过了之后,每秒钟就 50 个请求进 MQ,但是 A 系统依然会按照每秒 2k 个请求的速度在处理。所以说,只要高峰期一过,A 系统就会快速将积压的消息给解决掉。

消息队列有什么优缺点
优点上面已经说了,就是在特殊场景下有其对应的好处,解耦、异步、削峰。

缺点有以下几个:
系统可用性降低
系统引入的外部依赖越多,越容易挂掉。本来你就是 A 系统调用 BCD 三个系统的接口就好了,ABCD 四个系统还好好的,没啥问题,你偏加个 MQ 进来,万一 MQ 挂了咋整?MQ 一挂,整套系统崩溃,你不就完了?如何保证消息队列的高可用,可以点击这里查看。

系统复杂度提高
硬生生加个 MQ 进来,你怎么保证消息没有重复消费?怎么处理消息丢失的情况?怎么保证消息传递的顺序性?头大头大,问题一大堆,痛苦不已。

一致性问题
A 系统处理完了直接返回成功了,人都以为你这个请求就成功了;但是问题是,要是 BCD 三个系统那里,BD 两个系统写库成功了,结果 C 系统写库失败了,咋整?你这数据就不一致了。
所以消息队列实际是一种非常复杂的架构,你引入它有很多好处,但是也得针对它带来的坏处做各种额外的技术方案和架构来规避掉,做好之后,你会发现,妈呀,系统复杂度提升了一个数量级,也许是复杂了 10 倍。但是关键时刻,用,还是得用的。

1.认识rabbitmq

一款基于AMQP(高级消息队列协议)用于软件之间通信的中间件由Rabbit科技有限公司开发,服务器
端用Erlang语言编写,支持多种客户端,如:Python、Ruby、。NET、Java、JMS、C、PHP、
ActionScript、XMPP、STOMP等。用于在分布式系统中存储转发消息,在易用性、扩展性、高可用性等方面表现不俗。
Rabbitmq四大核心:生产者、消费者、队列、交换机
AMQP协议是一种二进制协议,它定义了一组规则和标准,!以确保消息可以在不同的应用程序和平台之间传递和解释,AMQP协议包含四个核心组件:消息、交换机、队列、绑定

1.1 rabbitmq工作原理

在这里插入图片描述
Broker: 接收和分发消息的应用,RabbitMQ Server就是Message Brolker。
Virtual host: Virtual host是一个虚拟主机的概念,一个Broker中可以有多个Virtualhost,每个Virtual host都有一套自己的Exchange和Queue,同一个Virtual host中的Excharge和Queue不能重名,不同的Virtual host中的Exchange和Queue名字可以一样,这样,不同的用户在访问同一个RabbitMQ Broker时,可以创建自己单独的Virtual host,然后在自己的Virtual host中创建Exchange和Queue,很好地做到了不同用户之间相互隔离的效果。
Connection: publisher/consumer和borker之间的TCP连接
Channel: 发送消息的通道,如果每一次访问RabbitMQ都建立一个Connection,在消息量大的时候建立TCP Connection的开销将是巨大的,效率也较低,Channel是在Connection内部建立的逻辑连接,如果应用程序支持多线程,通常每个thread创建单独的Connection进行通讯,AMQP method包含了Channel id帮助客户端和message broker识别Channel,所以Channel之间是完全隔离的Channel作为轻量级Connection极大减少了操作系统建立TCP connection的开销
Exchange: message到达broker的第一站,根据分发规则,匹配直询表中的routing key,分发消息到queue中去。常用的类型有:direct(point-to-point),topic(publish-subscribe) and fanout (multicast)
Queue: Queue是一个用来存放消息的队列,生产者发送的消息会被放到Queue中,消费者消费消息时也是从Queue中取走消息。
Binding: exchange和queue之间的虚拟连接,binding中可以包含routingkey,Binding信息被保存
到exchange中的查询表中,用于message的分发依据。

2.认识kafka

Kafka 是一个分布式流式处理平台。

流平台具有三个关键功能:
消息队列: 发布和订阅消息流,这个功能类似于消息队列,这也是 Kafka 也被归类为消息队列的原因。
容错的持久方式存储记录消息流: Kafka 会把消息持久化到磁盘,有效避免了消息丢失的风险。
流式处理平台: 在消息发布的时候进行处理,Kafka 提供了一个完整的流式处理类库。

Kafka 主要有两大应用场景:
消息队列: 建立实时流数据管道,以可靠地在系统或应用程序之间获取数据。
数据处理: 构建实时的流数据处理程序来转换或处理数据流。

2.1 kafka工作原理

在这里插入图片描述
上面这张图也为我们引出了,Kafka 比较重要的几个概念:
Producer(生产者) : 产生消息的一方。
Consumer(消费者) : 消费消息的一方。
Broker(代理): 可以看作是一个独立的 Kafka 实例。多个 Kafka Broker 组成一个 Kafka Cluster。同时,你一定也注意到每个 Broker 中又包含了 Topic 以及 Partition 这两个重要的概念:
Topic(主题) : Producer 将消息发送到特定的主题,Consumer 通过订阅特定的 Topic(主题) 来消费消息。
Partition(分区) : Partition 属于 Topic 的一部分。一个 Topic 可以有多个 Partition ,并且同一 Topic 下的 Partition 可以分布在不同的 Broker 上,这也就表明一个 Topic 可以横跨多个 Broker 。

3. 消息队列中遇到的问题

系统引入的外部依赖越多,越容易挂掉,硬生生加个 MQ 进来,怎么保证消息没有重复消费?怎么处理消息丢失的情况?怎么保证消息传递的顺序性?

3.1 如何保证消息不被重复消费?或者说,如何保证消息消费的幂等性?

我们先了解一下我们是怎么消费消息的,一个消费者启动时,offset会被初始化为0,这代表我们从0开始消费,每消费一条消息,offset会递增一次。如果一直正常消费(消费者不故障)是不会导致消息重复消费以及漏消息的。但是当以下两种情兄发生时,会分别发生漏消息与重复消费消息的情况:
1、先提交offset,再消费消息(漏消息)
offset被提交到kafka broker,但是消息还没来得及被消费,消费者故障了需要重启,由于offset已经被提交了,所以这个情况会发生漏消费的问题。
在这里插入图片描述
1、先消费消息,再提交offset(重复消息)
先把消息消费完了,但offset还未被提交,消费者故障重启,消息已经被消费,但offset未提交,此时故障会产生消息重复消费的问题。
在这里插入图片描述
如何避免消息重复消费、漏消费的情况?
1、如果消息有ID主键的话,那么先消费数据、再提交offset,这样首先保证了不会丢失数据,在消费数据时我们可以添加检测操作,如果消息已经存在db中或内存中,我们就不进行本次操作。这样我们可以跃过已经重复消费的数据。这样可以浪费一点资源来保全我们的数据不重复消费也不漏消费。
在这里插入图片描述
2、根据事务的特性,一组操作要么全部成功,要么全部失败,我们可以将(消费者消费数据,消费者提交offset)两个操作都在一个事务中进行,进而保证两个操作同时成功或失败、达到我们既不重复消费数据也不漏消费消息的目的。

如果是消费kafka中的topic,并且将结果写回到kafka中另外的topic,可以将消息处理后结果的保存和offset的保存绑定为一个事务,这时就能采证消息的处理和offset的提交要么都成功,要么都失败。

如果是将处理消息后的结果保存到外部系统,这时就要用到两阶段提交(tow-phase commit),但是这样做很麻烦,较好的方式是offset自己管理,将它和消息的结果保存到同一个地方,整体上进行绑定

3.2 如何保证消息的顺序性?

3.3 如何保证消息队列的高可用?

3.4 如何解决消息队列的延时以及过期失效问题?消息队列满了以后该怎么处理?有几百万消息持续积压几小时,说说怎么解决?

3.5 如何保证消息的可靠性传输?(如何处理消息丢失的问题)

3.6 如果让你写一个消息队列,该如何进行架构设计啊?说一下你的思路。

  • 8
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
Uniapp 是基于Vue.js开发的一套跨平台应用开发框架,可以通过一套代码同时开发iOS和安卓应用。而MQ(消息队列)是一种基于异步通信的系统,用于处理大量消息的传输和存储。 在Uniapp开发安卓应用中使用MQ,可以借助第三方插件来实现。例如,可以使用UniMQ插件,在Uniapp项目中引入该插件后,即可使用MQ相关的API来进行开发。 首先,我们需要安装UniMQ插件,并在项目配置文件中进行相关配置。然后,可以在需要使用MQ的页面或组件中引入UniMQ插件,并创建一个MQ实例。 在创建MQ实例后,我们可以使用MQ实例提供的方法,如"send"和"receive"来发送和接收消息。通过"send"方法,我们可以将需要传输的消息发送到指定的队列中;而通过"receive"方法,我们可以从指定的队列中接收消息。 在接收消息时,可以将消息进行处理,并根据需要进行相应操作。例如,可以将接收到的消息展示在页面上,或根据消息内容执行特定的逻辑。 同时,UniMQ插件也提供了其他一些常用的方法,如"subscribe"和"unsubscribe"等,用于订阅和取消订阅指定的消息主题。 需要注意的是,使用MQ的同时,我们也需要保证MQ服务器的正常运行。因此,在开发安卓应用时,我们需要提前搭建好MQ服务器,并确保应用能够正常连接和与之通信。 总结来说,Uniapp开发安卓应用中使用MQ可以借助第三方插件,通过相关的API进行消息队列的发送和接收。这样可以方便地处理大量的异步消息,并根据需要对消息进行相应的处理操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值