Apache RocketMQ 从入门到实战 (丁威) (Z-Library)
Author: it-ebooks
教育
No Description
📄 File Format:
PDF
💾 File Size:
4.2 MB
28
Views
0
Downloads
0.00
Total Donations
📄 Text Preview (First 20 pages)
ℹ️
Registered users can read the full content for free
Register as a Gaohf Library member to read the complete e-book online for free and enjoy a better reading experience.
📄 Page
1
(This page has no text content)
📄 Page
2
扫一扫加入作者公众号 扫一扫关注 中间件兴趣圈 RocketMQ官微 扫一扫关注【阿里巴巴云原生】公众号 阿里云开发者“藏经阁” 获取第一手技术干货 海量免费电子书下载
📄 Page
3
作者简介 作者简介 丁威,《RocketMQ 技术内幕》作者,RocketMQ 官方社区优秀布道师,荣获 CSDN2020 博客之星亚军;担任中通快递研发中心资深架构师,维护『中间件兴趣圈』公 众号,主打成体系剖析 Java 主流中间件,尝试从源码分析、架构设计、实战、故障分析等 维度深刻揭晓中间件技术,已覆盖 RocketMQ、Dubbo、Sentienl、Kafka、Canal、 MyCat、ElasticJob、ElasticSearch 等。
📄 Page
4
推荐人及推荐序 推荐人 杜恒,Apache RocketMQ PMC Member/ committer,Linux OpenMessaging TSC Member,目前负责 RocketMQ 专有云商业化以 及开源技术生态构建。具有多年分布式系统、中间件 研究及工程经验。目前对分布式中间件、K8s、微服 务、物联网、Serverless 感兴趣。 推荐序 Apache RocketMQ 作为一款高吞吐,抗万亿消息堆积的云原生消息平台,目前已 经被国内 75% 以上互联网、金融等公司所采用,逐渐成为企业 IT 架构的核心基础设施。 丁威老师作为资深架构师,在分布式架构、存储方面功底深厚,目前在企业内部负责着 日均千亿级消息流转的 RocketMQ 集群。本书不仅由浅入深的介绍了 RocketMQ 的架 构与实现,而且包含了多年线上超大规模集群开发运维经验的总结,通过本书不仅能够掌握 分布式消息平台的设计原理,对线上疑难问题排查分析、性能调优与架构设计也大有帮助。
📄 Page
5
目录 开篇:我的另一种参与 RocketMQ 开源社区的方式 6 1.1 RocketMQ核心概念扫盲篇 10 1.2 生产环境中,autoCreateTopicEnable为什么不能设置为 true 18 1.3 实战:RocketMQ学习环境搭建指南篇 28 1.4 RocketMQ HA 核心工作机制 39 1.5 踩坑记:rocketmq-console 消费 TPS为 0,但消息积压数却在降低是个什么 “鬼” 49 1.6 RocketMQ一个新的消费组初次启动时从何处开始消费呢? 64 1.7 一次 RocketMQ 进程自动退出排查经验分享 78 1.8 RocketMQ主题扩分片后遇到的坑 82 1.9 RocketMQ消息发送 system busy、broker busy原因分析与解决方案坑 91 1.10 再谈 RocketMQ broker busy 104 1.11 从年末生产故障解锁 RocketMQ集群部署的最佳实践 108 1.12 RocketMQ一行代码造成大量消息丢失 115 1.13 RocketMQ DLedger多副本即主从切换实战 121 1.14 RocketMQ msgId与 offsetMsgId释疑 131 1.15 RocketMQ ACL使用指南 141 1.16 RocketMQ消息轨迹-设计篇 151 1.17 消息发送常见问题与解决方案 155
📄 Page
6
本文来自『中间件兴趣圈』公众号,仅作技术交流,未授权任何商业行为。 开篇:我的另一种参与 RocketMQ 开源社区的方式 < 6 开篇:我的另一种参与 RocketMQ 开源 社区的方式 很荣幸在 2019 年获得了RocketMQ 开源社区的授予我优秀布道师荣誉称号。 说到参与开源项目,很多人都理解为成为一名 Committer 才能算式参与到开源社区的 建设?但其实这个就是参与开源项目有代码层面的贡献,也有非代码贡献层面的如技术布道 、社区运营(线上直播、线下活动、文档编辑)等。如何参与一个开源项目,容我慢慢道来。 一、与 RocketMQ 相识、相知到“在一起” 在 2017 年听到阿里巴巴将 RocketMQ 捐赠给 Apache 基金会成为 Apache 的顶 级项目,我内心是无比激动,因为终于可以一睹一款高性能的消息中间件的实现原理。 通过阅读了 RocketMQ 官方,以下几个特别的点更是吸引了我的注意,让我下定决 心深入研究一番。
📄 Page
7
本文来自『中间件兴趣圈』公众号,仅作技术交流,未授权任何商业行为。 7 > 开篇:我的另一种参与 RocketMQ 开源社区的方式 RocketMQ 为什么性能高效,到底运用了什么“厉害”的技术? RocketMQ 如何实现刷盘(可以类比一下数据库方面的刷盘、redo、undo 日志)? RocketMQ 文件存储设计理念、基于文件的 Hash 索引是怎么实现的? 定时消息、消息过滤等实现原理。 如何进行网络编程(Netty 实战)? 下定决心后便开始了我的源码分析 RocketMQ 之旅,大概在 4个多月的时间中连续 发表了 30 余篇文章,从 Nameserver、消息发送高可用设计、消息存储、消息消费、消 息过滤、事务消息等各个方面对其进行了体系化的剖析,边写边分享,边分享边传播,终于 得到了机械工业出版社华章分社的杨福川老师的认可,邀请我出书。 在杨老师和张工的帮助与指点下,经过将近半年的努力,书稿基本完稿。由于我当时是 一位名不经传的新人,按照出版行业的惯例,需要找一些该领域内专家大牛帮忙做序或写写 推荐语。当时我也是初生牛犊不怕虎,蹦出了一个非常大胆的想法,是不是可以联系到 RocketMQ 官方的一些大佬,最终我直接锁定了 RocketMQ 创始人冯嘉大神,希望他 能帮我作序推荐,令人惊喜的是冯嘉大神非常平易见人,得知我的来意后,他说了这样一句 话:“我是非常愿意为写书的朋友作序,但需要评估一下书稿的质量,如果质量OK,非常 愿意效劳”。我备受鼓舞,在和出版社初步沟通后,将试读稿件再加上消息存储整章的内容 发给冯嘉大神后,经冯嘉大神认真审稿后,决定帮忙推荐作序,真的非常受鼓舞。 随着《RocketMQ技术内幕》一书的正式出版上市,并得到广大读者朋友的认可,与 官方的联系也越来越多,后面在 RocketMQ 中国社区负责人青峰大佬的筹备下,我还参 与了 RocketMQ 官方社区的源码解析直播活动、官方文档审稿等工作,并在社区得到了 不错的反响。 说到这里大家是不是觉得非常奇怪,是不是都认为你只是在写文章,写书,没有真正参 与开源社区呀,没有贡献代码,这个算哪门子参与开源社区? 其实我一开始连我自己也没有意识到我正在参与一个开源项目,直到我在冯嘉大神为我 写的序言中给了我一个新的称号:RocketMQ布道师,从而才真正了解到参与开源的另外 一种方式:做一个开源项目的传播者,让更多人更容易的应用它,即降低大众对它的使用门 槛。
📄 Page
8
本文来自『中间件兴趣圈』公众号,仅作技术交流,未授权任何商业行为。 开篇:我的另一种参与 RocketMQ 开源社区的方式 < 8 有了新的称号,那就得更加努力,朝着优秀努力,在 2019 年我又陆续发表了 20 几篇 关于 RocketMQ 相关的文章,这些文章含金量极高,不仅及时跟进了RocketMQ4.3.0 之后的新特性:消息轨迹、ACL、主从切换等机制,更是发表了数篇实战类文章,详细指 出在生产环境下一些使用误区,更是输出了几篇生产环境真实故障与解决方案。最终于 20 19 年 RocketMQ 官方社区授予我优秀布道师荣誉称号。 RocketMQ 成就了我,我也会继续努力,为传播RocketMQ尽一份力所能及的力量。 2020 年,继续努力。 二、如何成为开源项目的 Committer 有一些粉丝在问我,您对 RocketMQ 研究的这么深入,为什么不考虑贡献代码,成 为一名 Committer 呢?这是因为参与开源项目需要具备一些基本条件,当下我的实际情 况不符合,那成为一个开源项目的 Committer 有些什么条件呢? 1. 扎实的 Java 基础功底 一个开源项目的底层都会涉及到存储,这就要求具备一定的数据结构基础,JAVA 集 合框架中的类自然成为了我们突破数据结构最好的老师,其次是 java 并发,即多线程、并 发容器、锁等课题,这方面可以好好学习一下 JUC框架。最后最好是具备一些网络方面的 知识,例如NIO、Netty。 2. 持续输出能力 成为一个开源项目的 contributions 非常容易,提交一个PR并被通过即可,甚至于 提交一个文档被接受也同样可以,难的是持续贡献,最终被开源项目的PMC认为对该项目 有着突出贡献。 我比较“苦逼”,在带娃方面我的资源只有我老婆,父母在老家无法分身,故下班后我 没有连续的空闲时间专心投入一项任务中,而开源最需要的是精益求精,不只是需要完成功 能,而是要编写结构优良的代码,设计所占据的时间比代码开发时间要多的多,故我个人认 为我暂时不方便走代码贡献这条道路。但我零碎时间还是充足的,故现阶段我会好好利用这 些零碎时间,继续通过写文章的方式为开源项目贡献自己的一份力量。
📄 Page
9
本文来自『中间件兴趣圈』公众号,仅作技术交流,未授权任何商业行为。 9 > 开篇:我的另一种参与 RocketMQ 开源社区的方式 接下来我们回到本节的主题,那如何参与一个开源项目呢? 在参与一个开源项目之前,我觉得第一个最基本的步骤还是要打牢基础,这里的基础至 少要包括 JAVA集合、JAVA并发(JUC)这两项,只是最最基本的,至少要阅读其源码, 理解其设计理念,至于NIO,Netty 这些可以后续在需要使用时再去专门学习,有针对性 的学习,有使用需求,或许学习动力更强劲,学习效率更高效。 当具备一定的基础后,如何从零开始参与进开源项目呢?通常有如下几个方法: 看看官方文档,特别是设计手册,从整体上把握其设计理念。 写写源码分析类文章,从整体上把控这个框架,这个花费时间较多,如果框架正在起步。 阶段,不建议该方法;如果框架比较成熟,非常建议采用该方法。 尝试看看开源项目中的 issues,看能不能解决,从问题入手,快速融入该项目。 尝试谢谢单元测试用例,测试驱动开发,借此学习该框架。 后面的事情就是坚持不懈,朝着目标不断前进,中途可以放慢速度,但千万别放弃,因 为只有坚持,才能胜利,只要前进,就离目标更近。 参与开源,一个最基本的条件是拥有大量的连续时间,想要成为一个开源框架的 Committer ,唯有坚持不懈,持续投入,持续产出。 最后再次感谢 RocketMQ 社区对我的认可,我会尽努力做出更大的贡献,也希望广 大读者朋友们,积极参与开源社区,贡献一份自己的力量,同事打造自身影响力,助力职场 步步高升。
📄 Page
10
本文来自『中间件兴趣圈』公众号,仅作技术交流,未授权任何商业行为。 1.1 RocketMQ核心概念扫盲篇 < 10 1.1 RocketMQ核心概念扫盲篇 在正式进入RocketMQ的学习之前,我觉得有必要梳理一下RocketMQ 核心概念, 为大家学习RocketMQ打下牢固的基础。 一、RocketMQ部署架构 在RocketMQ主要的组件如下: 1. Nameserver Nameserver 集群,topic 的路由注册中心,为客户端根据 Topic 提供路由服务,从 而引导客户端向 Broker 发送消息。Nameserver 之间的节点不通信。路由信息在 Nameserver 集群中数据一致性采取的最终一致性。 2. Broker 消息存储服务器,分为两种角色:Master 与 Slave,上图中呈现的就是 2主 2从的部 署架构,在RocketMQ中,主服务承担读写操作,从服务器作为一个备份,当主服务器存 在压力时,从服务器可以承担读服务(消息消费)。所有Broker,包含 Slave 服务器每隔 30s 会向 Nameserver 发送心跳包,心跳包中会包含存在在 Broker 上所有的 topic 的路 由信息。
📄 Page
11
本文来自『中间件兴趣圈』公众号,仅作技术交流,未授权任何商业行为。 11 > 1.1 RocketMQ核心概念扫盲篇 3. Client 消息客户端,包括Producer(消息发送者)和 Consumer(消费消费者).客户端在同一 时间只会连接一台 nameserver,只有在连接出现异常时才会向尝试连接另外一台。客户 端每隔 30s 向 Nameserver 发起 topic 的路由信息查询。 温馨提示:Nameserver 是在内存中存储 Topic 的路由信息,持久化Topic 路由信息 的地方是在Broker 中,即${ ROCKETMQ_HOME}/store/config/topics.json。 在 RocketMQ4.5.0 版本后引入了多副本机制,即一个复制组(m-s)可以演变为基 于 raft 协议的复制组,复制组内部使用 raft 协议保证 broker 节点数据的强一致性,该部署 架构在金融行业用的比较多。 二、消息订阅模型 在RocketMQ的消息消费模式采用的是发布与订阅模式。 topic:一类消息的集合,消息发送者将一类消息发送到一个主题中,例如订单模块将 订单发送到 order_topic 中,而用户登录时,将登录事件发送到 user_login_topic 中。 consumegroup:消息消费组,一个消费单位的“群体”,消费组首先在启动时需要 订阅需要消费的 topic。一个 topic 可以被多个消费组订阅,同样一个消费组也可以订阅多 个主题。一个消费组拥有多个消费者。 术语解释起来有点枯燥晦涩,接下来我举例来阐述。 例如我们在开发一个订单系统,其中有一个子系统:order-service-app,在该项目 中会创建一个消费组 order_consumer 来订阅 order_topic,并且基于分布式部署, order-service-app 的部署情况如下:
📄 Page
12
本文来自『中间件兴趣圈』公众号,仅作技术交流,未授权任何商业行为。 1.1 RocketMQ核心概念扫盲篇 < 12 即 order-service-app 部署了 3 台服务器,每一个 jvm 进程可以看做是消费组 order_consumer 消费组的其中一个消费者。 1. 消费模式 那这三个消费者如何来分工来共同消费 order_topic 中的消息呢? 在RocketMQ中支持广播模式与集群模式。 广播模式:一个消费组内的所有消费者每一个都会处理 topic 中的每一条消息,通常用 于刷新内存缓存。 集群模式:一个消费组内的所有消费者共同消费一个 topic 中的消息,即分工协作,一 个消费者消费一部分数据,启动负载均衡, 集群模式是非常普遍的模式,符合分布式架构的基本理念,即横向扩容,当前消费者如 果无法快速及时处理消息时,可以通过增加消费者的个数横向扩容,快速提高消费能力,及 时处理挤压的消息。 2. 消费队列负载算法与重平衡机制 那集群模式下,消费者是如何来分配消息的呢? 例如上面实例中 order_topic 有 16 个队列,那一个拥有 3个消费者的消费组如何来分 配队列中。
📄 Page
13
本文来自『中间件兴趣圈』公众号,仅作技术交流,未授权任何商业行为。 13 > 1.1 RocketMQ核心概念扫盲篇 在MQ领域有一个不成文的约定:同一个消费者同一时间可以分配多个队列,但一个 队列同一时间只会分配给一个消费者。 RocketMQ提供了众多的队列负载算法,其中最常用的两种平均分配算法。 AllocateMessageQueueAveragely 平均分配 AllocateMessageQueueAveragelyByCircle 轮流平均分配 为了说明这两种分配算法的分配规则,现在对 16 个队列,进行编号,用 q0~q15 表示, 消费者用 c0~c2表示。 AllocateMessageQueueAveragely 分配算法的队列负载机制如下: c0:q0 q1 q2 q3 q4 q5 c1: q6 q7 q8 q9 q10 c2: q11 q12 q13 q14 q15 其算法的特点是用总数除以消费者个数,余数按消费者顺序分配给消费者,故 c0 会多 分配一个队列,而且队列分配是连续的。 AllocateMessageQueueAveragelyByCircle 分配算法的队列负载机制如下: c0:q0 q3 q6 q9 q12 q15 c1: q1 q4 q7 q10 q13 c2: q2 q5 q8 q11 q14
📄 Page
14
本文来自『中间件兴趣圈』公众号,仅作技术交流,未授权任何商业行为。 1.1 RocketMQ核心概念扫盲篇 < 14 该分配算法的特点就是轮流一个一个分配。 温馨提示:如果 topic 的队列个数小于消费者的个数,那有些消费者无法分配到消息。 在RocketMQ中一个 topic 的队列数直接决定了最大消费者的个数,但 topic 队列个数的 增加对RocketMQ的性能不会产生影响。 在实际过程中,对主题进行扩容(增加队列个数)或者对消费者进行扩容、缩容是一件非 常寻常的事情,那如果新增一个消费者,该消费者消费哪些队列呢?这就涉及到消息消费队 列的重新分配,即消费队列重平衡机制。 在RocketMQ 客户端中会每隔 20s 去查询当前 topic 的所有队列、消费者的个数,运 用队列负载算法进行重新分配,然后与上一次的分配结果进行对比,如果发生了变化,则进 行队列重新分配;如果没有发生变化,则忽略。 例如采取的分配算法如下图所示,现在增加一个消费者 c3,那队列的分布情况是怎样 的呢? 根据新的分配算法,其队列最终的情况如下: c0:q0 q1 q2 q3 c1: q4 q5 q6 q7 c2: q8 q9 q10 q11 c3: q12 q13 q14 q15
📄 Page
15
本文来自『中间件兴趣圈』公众号,仅作技术交流,未授权任何商业行为。 15 > 1.1 RocketMQ核心概念扫盲篇 上述整个过程无需应用程序干预,由RocketMQ完成。大概的做法就是将将原先分配 给自己但这次不属于的队列进行丢弃,新分配的队列则创建新的拉取任务。 3. 消费进度 消费者消费一条消息后需要记录消费的位置,这样在消费端重启的时候,继续从上一次 消费的位点开始进行处理新的消息。在RocketMQ 中,消息消费位点的存储是以消费组为 单位的。 集群模式下,消息消费进度存储在 broker 端,${ROCKETMQ_HOME}/store/conf ig/consumerOffset.json 是其具体的存储文件,其中内容截图如下: 可见消费进度的Key 为:topic@consumeGroup,然后每一个队列一个偏移量。 广播模式的消费进度文件存储在用户的主目录,默认文件全路劲名:${USER_HOM E}/.rocketmq_offsets。 4. 消费模型 RocketMQ提供了并发消费、顺序消费两种消费模型。 并发消费:对一个队列中消息,每一个消费者内部都会创建一个线程池,对队列中的消 息多线程处理,即偏移量大的消息比偏移量小的消息有可能先消费。 顺序消费:在某一项场景,例如MySQL binlog 场景,需要消息按顺序进行消费。在 RocketMQ中提供了基于队列的顺序消费模型,即尽管一个消费组中的消费者会创建一个 多线程,但针对同一个Queue,会加锁。 温馨提示:并发消费模型中,消息消费失败默认会重试 16 次,每一次的间隔时间不一 样;而顺序消费,如果一条消息消费失败,则会一直消费,直到消费成功。故在顺序消费的
📄 Page
16
本文来自『中间件兴趣圈』公众号,仅作技术交流,未授权任何商业行为。 1.1 RocketMQ核心概念扫盲篇 < 16 使用过程中,应用程序需要区分系统异常、业务异常,如果是不符合业务规则导致的异常, 则重试多少次都无法消费成功,这个时候一定要告警机制,及时进行人为干预,否则消费会 积压。 三、事务消息 事务消息并不是为了解决分布式事务,而是提供消息发送与业务落库的一致性,其实现 原理就是一次分布式事务的具体运用,请看如下示例: 上述伪代码中,将订单存储关系型数据库中和将消息发送到MQ这是两个不同介质的 两个操作,如果能保证消息发送、数据库存储这两个操作要么同时成功,要么同时失败, RocketMQ为了解决该问题引入了事务消息。 温馨提示,本节主要的目的是让大家知晓各个术语的概念,由于事务消息的使用,将在 该专栏的后续文章中详细介绍。 四、定时消息 开源版本的RocketMQ目前并不支持任意精度的定时消息。所谓的定时消息就是将消 息发送到 Broker,但消费端不会立即消费,而是要到指定延迟时间后才能被消费端消费。
📄 Page
17
本文来自『中间件兴趣圈』公众号,仅作技术交流,未授权任何商业行为。 17 > 1.1 RocketMQ核心概念扫盲篇 RocketMQ目前支持指定级别的延迟,其延迟级别如下: 1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h 五、消息过滤 消息过滤是指消费端可以根据某些条件对一个 topic 中的消息进行过滤,即只消费一个 主题下满足过滤条件的消息。 RocketMQ目前主要的过滤机制是基于 tag 的过滤与基于消息属性的过滤,基于消息 属性的过滤支持SQL92 表达式,对消息进行过滤。 六、小结 本文的主要目的是介绍RocketMQ 常见的术语,例如 nameserver、broker、主题、 消费组、消费者、队列负载算法、队列重平衡机制、并发消费、顺序消费、消费进度存储、 定时消息、事务消息、消息过滤等基本概念,为后续的实战系列打下坚实基础。 从下一篇开始,将正式开始RocketMQ 之旅,开始学习消息发送。
📄 Page
18
本文来自『中间件兴趣圈』公众号,仅作技术交流,未授权任何商业行为。 1.2 生产环境中,autoCreateTopicEnable 为什么不能设置为 true < 18 1.2 生产环境中,autoCreateTopicEn able 为什么不能设置为 true 一、现象 很多网友会问,为什么明明集群中有多台Broker 服务器,autoCreateTopicEnable 设置为 true,表示开启 Topic 自动创建,但新创建的 Topic 的路由信息只包含在其中一台 Broker 服务器上,这是为什么呢? 期望值:为了消息发送的高可用,希望新创建的 Topic 在集群中的每台 Broker 上创 建对应的队列,避免Broker 的单节点故障。 现象截图如下: Broker 集群信息 自动创建的 topicTest5 的路由信息: topicTest5 只在 broker-a 服务器上创建了队列,并没有在 broker-b 服务器创建队 列,不符合期望。
📄 Page
19
本文来自『中间件兴趣圈』公众号,仅作技术交流,未授权任何商业行为。 19 > 1.2 生产环境中,autoCreateTopicEnable为什么不能设置为 true 默认读写队列的个数为 4。 我们再来看一下RocketMQ默认 topic 的路由信息截图如下: 从图中可以默认Topic 的路由信息为 broker-a、broker-b 上各 8个队列。 二、思考 默认 Topic 的路由信息是如何创建的? Topic 的路由信息是存储在哪里?Nameserver?broker? RocketMQ Topic 默认队列个数。 三、原理 1. RocketMQ基本路由规则
📄 Page
20
本文来自『中间件兴趣圈』公众号,仅作技术交流,未授权任何商业行为。 1.2 生产环境中,autoCreateTopicEnable 为什么不能设置为 true < 20 Broker 在启动时向Nameserver 注册存储在该服务器上的路由信息,并每隔 30s 向 Nameserver 发送心跳包,并更新路由信息。 Nameserver 每隔 10s 扫描路由表,如果检测到Broker 服务宕机,则移除对应的路 由信息。 消息生产者每隔 30s 会从 Nameserver 重新拉取 Topic 的路由信息并更新本地路由 表;在消息发送之前,如果本地路由表中不存在对应主题的路由消息时,会主动向 Nameserver 拉取该主题的消息。 回到本文的主题:autoCreateTopicEnable,开启自动创建主题,试想一下,如果生 产者向一个不存在的主题发送消息时,上面的任何一个步骤都无法获取一个不存在的主题的 路由信息,那该如何处理这种情况呢? 在 RocketMQ 中,如果 autoCreateTopicEnable 设置为 true,消息发送者向 NameServer 查询主题的路由消息返回空时,会尝试用一个系统默认的主题名称( MixAll.AUTO_CREATE_TOPIC_KEY_TOPIC),此时消息发送者得到的路由信息为:
The above is a preview of the first 20 pages. Register to read the complete e-book.