MQ系列--核心基础篇


 

 文章来源(建议大家阅读原文):《吃透 MQ 系列》之核心基础篇




一、什么是MQ?

MQ的本质就是一发一存一消费”。

生产者把消息投递到队列中,然后从队列中取出消息,发送给消费者。

图片




二、MQ演化

常用的MQ有RocketMQ、Kafka等,都是基于最原始的消息模型做扩展,同时支持一些新的特性,如:主题topic、分区partition、队列queue等。

要理解这些MQ,可以先从最简单的模型演化(架构都是不断演化而来的,并非一开始就设计的很完美)。

1. 队列模型

上面说的最简单的模型就是队列模型,FIFO。不多这个队列的“读”,就是从队列中删除这个消息。但是,一个消息只能给一个消费者,不支持多个消费者消费同一个消息。

图片




2.发布订阅模型

如果需要把同一个消息给多个消费者消费,每个消费者都要求收到全量的消息。显然队列模型不能满足该需求。

一种可行的方案:为每个消费者创建一个队列,生产者发送多份消息。这种做法,一份数据会复制多份,很浪费空间。

另一种解决方案就解决了这个问题:发布订阅模型。

图片

在发布订阅模型中,存放消息的容器变成了主题topic,订阅者可以指定订阅的主题topic。最终每个订阅者都可以收到同一个主题的全量消息。

他和队列模式的异同:生产者就是发布者,消费者就是订阅者,队列就是主题topic,无本质区别。唯一的区别:一份消息能否被多次消费。

3.小结

两种模式,就是单播和广播的区别。当发布订阅模式只有一个订阅者时,它就和队列模式一样了。所以这也解释了为什么现代主流的RocketMQ、Kafka都是直接基于发布订阅模式实现的。

三、MQ的应用场景

目前,MQ的应用场景非常多:系统解耦、异步通信和流量削峰。除此之外,还有延迟通知、最终一致性保证、顺序消息、流式处理等。所以MQ的适配性很广。

举个栗子,比如说电商业务中最常见的订单支付场景:在订单支付成功后,需要更新订单状态、更新用户积分、通知商家有新的订单、更新推荐系统中的用户画像等。

图片

引入MQ后,订单支付现在只需要关注它最重要的流程:更新订单状态即可。其他的不重要的事情都交给MQ来通知。即实现系统解耦、异步通信。

改造前,订单系统依赖上个外部系统,改造后仅仅依赖MQ,而且后续业务扩展(如:营销系统针对支付用户奖励优惠券),也不会涉及订单系统的修改,从而保证了核心业务的稳定,降低了维护成本。

四、如何设计一个MQ?

1. 雏形

 MQ即“一发一存一消费”,从技术的角度来看MQ的通信模型:两次RPC+消息转储。

MQ雏形:

 a. 直接利用RPC框架,实现两个接口:发消息和读消息。

 b. 消息放在本地内存中存储。

2. 写一个适合生产环境的MQ

生产环境中的MQ,需要解决哪些问题呢?

  a. 高并发场景下,如何保证收发消息的性能?

  b. 如何保证消息服务的高可用和高可靠?

  c. 如何保证服务是可以水平扩展的?

  d. 如何保证消息存储是可以水平扩展的?

  e. 各种元数据(如集群中各个节点、主题topic、消费关系等)如何管理,需不需要考虑数据的一致性?

整体框架会涉及三类角色:

图片

将“一发一存一消费”进一步细化后,比较完整的数据流如下:

图片

三类角色的作用:

  a. Broker(服务端): MQ中最核心的部分,是MQ的服务端,为生产者和消费者提供RPC接口,负责消息的存储、备份和删除,以及消费关系的维护。

 b. Productor(生产者):调用Broker的RPC接口发送消息。

 c. Consumer(消费者):调用Broker提供的RPC接口接收消息,同时完成消费确认。

详细设计

下面展开讨论一些具体的技术难点和可行的解决方案。

  • 难点1:RPC通信

      可直接利用成熟的框架Dubbo/Thrift实现,这样就不用重复造轮子,不用考虑服务注册发现、负载均衡、通信协议、序列化方式等一系列的问题了。

  • 难点2:高可用设计

       主要是两个部分的高可用:Broker的高可用、消息存储的高可用。

      a. Broker的高可用,只需要保证Broker可水平扩展进行集群部署即可。进一步通过服务自动注册发现、负载均衡、超时重试机制、发送和消费消息时的ack机制来保证。

      b. 消息存储的高可用:1)参考Kafka的分区+多副本的模式,但是需要考虑分布式场景下数据复制和一致性方案(类似Zab、Raft协议),并实现自动故障转移; 2)可以用主流的DB、分布式文件系统、带持久化能力的KV数据库。

  • 难点3:高性能的存储设计

目前主流的方案:追加写日志文件(数据部分)+索引文件的方式,索引设计可以考虑稠密索引和稀疏索引,查找消息可以利用跳表、二分查找等,还可以通过操作系统的页缓存、零拷贝等技术来提升磁盘文件的读写性能。

  • 难点4:消费关系管理

为了支持发布订阅模式,Broker需要知道每个主题topic有哪些consumer订阅了,基于这个关系进行消息投递。

由于Broker是集群部署的,所以消费关系通常维护在公共存储上,可以基于Zookeeper等配置中心来管理以及进行变更通知。

  • 难点5:高性能设计

采用Reactor网络IO模型、业务线程池设计、生产端的批量发送、Broker的异步刷盘、消费端的批量拉取等。

小结:如何设计一个MQ?

 a. 需要从功能需求(一发一存一消费)和非功能需求(高性能、高可用、高扩展等)两方面入手;

 b. 功能性需求不是重点,能覆盖MQ的基础功能即可。至于延时消息、事务消息、重试队列等高级特性,是锦上添花的功能。

 c. 最核心的是:能结合功能性需求,理清楚整体的数据流,然后顺着这个思路去思考非功能性的需求如何满足,这才是难点!





总结

这篇文章从MQ 一发一存一消费 的本质出发,讲解了消息模型的演进过程,这是MQ的最核心的理论基础。

最后通过回答:如何设计一个MQ,来对MQ有一个更深入的认识和理解。

文章来源(建议大家阅读原文):《吃透 MQ 系列》之核心基础篇

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值