消息队列原理与实战| 青训营笔记

88 阅读4分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 11 天 

本文是对于掘金课程的课程笔记,针对课程内容的一些重难点、本人在学习消息队列知识时候进行的简单记录。

一、本堂课的重点内容

  1. 前世今生
  2. Kafka
  3. BMQ
  4. RocketMQ

二、详细知识点介绍

消息队列重要作用:解耦、削峰、异步、日志处理

前世今生

  • TIB
  • IBM MQ/WebSphre
  • SMQ
  • JMS
  • AMQP/RabbitMQ
  • Kafka(高吞吐)
  • RocketMQ(实时场景运用广)
  • Pulsar(下一代云原生分布式消息流平台)

Kafka

如何使用Kafka

  • 创建集群
  • 新增topic
  • 编写生产者逻辑
  • 编写消费者逻辑

基本概念

  • topic:逻辑队列
  • cluster:物理集群
  • producer:生产者,将业务消息发送到topic
  • consumer:消费者,消费topic中的消息
  • consumergroup:消费者组

一个集群有多个broker,其中会有一个broker作为controller,作为集群大脑;一个broker中有多个topic,每个topic有多个partition,同样的,每个broker中会有一个topic作为leader,其他则是follower;每个partition有多个replica,leader replica会在isr中选出。

问题:从一条消息的视角,为什么kafka能支撑那么高的吞吐?

producer->broker->consumer

producer

  • 采用批量发送,批量发送可以减少IO次数,从而加强发送能力
  • 采用数据压缩,减少消息大小,目前支持Snappy,ZSTD等

broker如何存储数据?

broker的消息文件结构

topic->partition->replica->log->logsegment(.log+.index+.timeindex+others)

broker通过顺序写来提高写入效率(末尾添加,减少寻道时间)

如何找到消息?

目标:寻找offset

  • 二分找到小于目标offset的最大文件(通过索引找到batch,该batch中可能含有)
  • 时间戳索引文件

数据拷贝

传统数据拷贝:

磁盘->read buffer->application buffer->socket buffer->nic buffer->消费者进程(从磁盘空间到内核空间,再带应用空间,再回到内核空间)

broker-零拷贝:使用系统调用,不需要再经过应用空间,降低3次内存拷贝次数

consumer

如何解决partition在consumer group的分配问题?

  • 手动分配,哪一个consumer消费哪一个partition完全由业务决定(不能自动容灾,新增机器会有数据中断问题,但是比较快)
  • 自动分配,选取一个broker当做coordinator,进行rebalance

kafka的缺点

  • 数据复制问题
  • 重启
  • 替换、扩容、缩容
  • 负载不均衡(partition迁走,又有数据复制问题)

问题总结:

  • 运维成本高
  • 对于复杂不均衡的场景,解决方案复杂
  • 没有自己的缓存,完全依赖page cache
  • controller和coordinator和broker在同一进程中,大量IO导致性能下降

BMQ

为了解决kafka的问题产生

简介:兼容kafka协议,存算分离,云原生消息队列

引入分布式存储系统和meta storage system,有点类似读写分离的思想

对于BMQ来说,重启、替换、扩容、缩容都可以在秒级完成

broker

写文件流程:messages->数据校验->buffer->writer thread->storage

如果datanode节点挂了或者其他原因导致我们写文件失败,如何处理?重新找一个可用的节点写入,创建segment,从而保证高可用

读取文件:fetch request->wait->cache->如果hit则return data,否则到storage(open file->seek->read)

  • 泳道消息:解决主干泳道流量隔离问题以及泳道资源重复创建问题
  • databus:原生SDK配合复杂,使用databus比较便利,支持动态配置
  • mirror:无法使用多机房部署来解决跨region读写问题,因此引入mirro,通过最终一致方式,解决跨region读写问题

RocketMQ

一般用在电商业务线,业务峰值时刻

相比kafka,多标签、生产者集群(为了支持事务消息)

存储模型

所有消息存储到commitlog,随后dispatch到consumerQueue,存的是索引

高级特性

  • 事务保证,(库存-1与消息队列),最终一致性
  • 事务消息(两阶段提交)
  • 延迟发送(scheduleMessage延迟服务)
  • 消息重试和死信队列(发送到scheduleTopic,如果超过重试错误发送到死信队列)

三、课后个人总结

通过本次课程,我重点掌握了kafka的基本构成,各个组件的结构特点,以及一个完整的消息消费流程,以及内部的一些高级特性,为什么kafka能够完成那么高的吞吐量,也了解了他的一些不足,随后引入的BMQ与RocketMQ各自解决了什么问题,与kafka的不同点、优势在哪里。在学习过程中,也发现各个知识点之间是会相互交汇的,学习消息队列也会有定时任务的课题,在学习定时任务以及分布式架构的时候也会有消息队列的身影,还有都学会了,再系统性地进行理解、实践、分类,才算做好了大项目开发的准备工作。