消息队列学习笔记 | 青训营

130 阅读8分钟

消息队列青训营学习笔记

简介:

  • 消息队列(MQ),指保存消息的一个容器,本质是个队列。但需要支持高吞吐,高并发,并且高可用,是分布式系统中的重要组件

1.png

  • 目前使用较多的消息队列有ActiveMQ,RabbitMQ,Kafka,RocketMQ。

  • Kafka:分布式,分区,多副本的日志提交服务,在高吞吐场景下发挥较为出色

  • RocketMQ:低延迟,强一致,高性能,高可靠,万亿级容量和灵活的可扩展性,在一些实时场景中运用较广

  • Rulsar:是下一代云原生分布式消息流平台,集消息,存储,轻量化函数式计算为一体,采用存算分离的架构设计

  • BMQ:和Pulsar架构类似,存算分离,初期定位是承接高吞吐的离线业务场景,逐步替换掉对应的Kafka集群

消息队列的好处

我觉得使用消息队列主要有两点好处:

1、通过异步处理提高系统性能(削峰、减少响应所需时间);

2.png

​ 如上图,在不使用消息队列服务器的时候,用户的请求数据直接写入数据库,在高并发的情况下数据库压力剧增,使得响应速度变慢。但是在使用消息队列之后,用户的请求数据发送给消息队列之后立即返回,再由消息队列的消费者进程从消息队列中获取数据,异步写入数据库。由于消息队列服务器处理速度快于数据库(消息队列也比数据库有更好的伸缩性),因此响应速度得到大幅改善。

​ 通过以上分析我们可以得出消息队列具有很好的削峰作用的功能——即通过异步处理,将短时间高并发产生的事务消息存储在消息队列中,从而削平高峰期的并发事务。 举例:在电子商务一些秒杀、促销活动中,合理使用消息队列可以有效抵御促销活动刚开始大量订单涌入对系统的冲击。

​ 因为用户请求数据写入消息队列之后就立即返回给用户了,但是请求数据在后续的业务校验、写数据库等操作中可能失败。因此使用消息队列进行异步处理之后,需要适当修改业务流程进行配合,比如用户在提交订单之后,订单数据写入消息队列,不能立即返回用户订单提交成功,需要在消息队列的订单消费者进程真正处理完该订单之后,甚至出库后,再通过电子邮件或短信通知用户订单成功,以免交易纠纷。这就类似我们平时手机订火车票和电影票。

消息队列带来的一些问题

  • 系统可用性降低: 系统可用性在某种程度上降低,为什么这样说呢?在加入MQ之前,你不用考虑消息丢失或者说MQ挂掉等等的情况,但是,引入MQ之后你就需要去考虑了!
  • 系统复杂性提高: 加入MQ之后,你需要保证消息没有被重复消费、处理消息丢失的情况、保证消息传递的顺序性等等问题!
  • 一致性问题: 我上面讲了消息队列可以实现异步,消息队列带来的异步确实可以提高系统响应速度。但是,万一消息的真正消费者并没有正确消费消息怎么办?这样就会导致数据不一致的情况了

Kafka:

  1. 使用场景:

3.png

  1. 如何使用:创建集群->新增Topic->编写生产者逻辑->编写消费者逻辑

  2. 基本概念:

4.png 4. 基本概念-Replica

*   每个分片有多个Replica,Leader Replica将会从ISR中选出

    

5.png

  1. 数据复制

6.png

  1. Kafka架构

7.png

  1. 一条消息的自述:Producer生产->Broker消费->Consumer

  2. Producer-数据压缩:通过压缩减少消息大小,目前支持Snappy,Gzip,LZ4,ZSTD压缩算法

  3. Kafka优点:

    • 解耦

    在项目启动之初来预测将来项目会碰到什么需求,是极其困难的。消息系统在处理过程中间插入了一个隐含的、基于数据的接口层,两边的处理过程都要实现这一接口。这允许你独立的扩展或修改两边的处理过程,只要确保它们遵守同样的接口约束。

    • 冗余(副本)

    有些情况下,处理数据的过程会失败。除非数据被持久化,否则将造成丢失。消息队列把数据进行持久化直到它们已经被完全处理,通过这一方式规避了数据丢失风险。许多消息队列所采用的"插入-获取-删除"范式中,在把一个消息从队列中删除之前,需要你的处理系统明确的指出该消息已经被处理完毕,从而确保你的数据被安全的保存直到你使用完毕。

    • 扩展性

    因为消息队列解耦了你的处理过程,所以增大消息入队和处理的频率是很容易的,只要另外增加处理过程即可。不需要改变代码、不需要调节参数。扩展就像调大电力按钮一样简单。

    • 灵活性&峰值处理能力

    在访问量剧增的情况下,应用仍然需要继续发挥作用,但是这样的突发流量并不常见;如果为以能处理这类峰值访问为标准来投入资源随时待命无疑是巨大的浪费。使用消息队列能够使关键组件顶住突发的访问压力,而不会因为突发的超负荷的请求而完全崩溃。

    • 可恢复性

    系统的一部分组件失效时,不会影响到整个系统。消息队列降低了进程间的耦合度,所以即使一个处理消息的进程挂掉,加入队列中的消息仍然可以在系统恢复后被处理。

    • 顺序保证

    在大多使用场景下,数据处理的顺序都很重要。大部分消息队列本来就是排序的,并且能保证数据会按照特定的顺序来处理。Kafka保证一个Partition内的消息的有序性。

    • 缓冲

    在任何重要的系统中,都会有需要不同的处理时间的元素。例如,加载一张图片比应用过滤器花费更少的时间。消息队列通过一个缓冲层来帮助任务最高效率的执行———写入队列的处理会尽可能的快速。该缓冲有助于控制和优化数据流经过系统的速度。

    • 异步通信

    很多时候,用户不想也不需要立即处理消息。消息队列提供了异步处理机制,允许用户把一个消息放入队列,但并不立即处理它。想向队列中放入多少消息就放多少,然后在需要的时候再去处理它们。

8.png

  1. 重启操作

9.png

  1. 负载不均衡

10.png

  1. 问题总结

    • 运维成本高
    • 对于负载不均衡的场景,解决方法复杂
    • 没有自己的缓存,完全依赖Page Cache
    • Controller和Coordinator和Broker在同一进程中,大量IO会造成其性能下降

BMQ:

  1. 架构图

11.png

  1. 运维操作对比

    具体操作KafkaBMQ
    重启需要数据复制,分钟级重启重启后可直接对外服务,秒级完成
    替换需要数据复制,分钟级替换,甚至天级别替换后可直接对外服务,秒级完成
    扩容需要数据复制,分钟级扩容,甚至天级别扩容后可直接对外服务,秒级完成
    缩容需要数据复制,分钟级缩容,甚至天级别缩容后可直接对外服务,秒级完成
  2. HDFS写文件流程

12.png

  1. 相较Kafka,BMQ文件结构

13.png

  1. Broker写文件流程

14.png 6. Proxy

15.png

  1. 多机房部署:

16.png

*   防止单机故障带来的影响
*   防止机房故障带来影响

8. 泳道消息

17.png

  1. Databus:

    直接使用原生SDK会有什么问题?

    1. 客户端配置复杂

    2. 不支持动态配置,更改配置需要停掉服务

    3. 对于latency不是很敏感的业务,batch效果不佳

18.png

  1. Mirror

19.png 使用mirror通过最终一致的方式,解决Region读写问题

RocketMQ:

  1. 使用场景:针对电商业务线,其业务涉及广泛,如注册,订单,库存,物流等,同时也会涉及许多业务峰值时刻,如秒杀活动,周年庆,定期特惠等

  2. 基本概念

    名称KafkaRocketMQ
    逻辑队列TopicTopic
    消息体MessageMessage
    标签Tag
    分区PartitionConsumerQueue
    生产者ProducerProducer
    生产者集群Producer Group
    消费者ConsumerConsumer
    消费者集群Consumer GroupConsumer Group
    集群控制器ControllerNameserver

20.png

  1. 架构

21.png

  1. 存储模型

22.png

  1. 高级特性

    • 事务场景

23.png

*   事务消息

   

24.png

*   延迟发送

   

25.png

*   延迟消息

   

26.png

*   处理失败(消费重试和死信队列)

   

27.png

总结

消息队列是一个非常重要的技术,用于异步处理,系统解耦,流量削峰,日志处理,生产者,消费者模型,在后面的学习中要继续参透,应用于实践