3.3.2 抽象拉取线程


3.3.2 抽象拉取线程

抽象拉取线程(AbstractFetcherThread)定义了拉取工作的主要流程,不同的实现类通过抽象方法嵌套在主流程中,保证了主流程执行的一致性。拉取线程工作时,首先要确定数据源(即拉取状态),每次拉取到消息还要更新拉取状态,确保下一次拉取请求时获得的拉取状态是最新的。

  1. 构建拉取请求

拉取管理器后台线程调用拉取线程的addPartitians()方法,partitionMap变量保存了每个分区的拉取状态。拉取线程的运行方法会根据拉取状态构建井处理拉取请求。相关代码如下:

在这里插入图片描述
注意:由于一个拉取线程要处理多个分区的拉取请求,因此抽象拉取线程要对partitionMap的操作加锁。同时它使用partitionMapCond作为锁的条件,用来在有数据时触发,没有数据时则等待。

  1. 处理拉取请求

消费者和备份副本的拉取工作都一样,拉取线程向服务端拉取消息的步骤如下。

(1)buildFetchRequest(partitionMap)根据partitionMap构建拉取请求。
(2)fetch(fetchRequest)根据拉取请求向目标节点拉取消息,并返回响应结果。
(3)processPartitionData(partitionData)处理拉取到的分区结果数据。

相关代码如下:
在这里插入图片描述
注意:抽象的拉取线程类调用一次doWork()方法表示执行一次拉取,但并不表示拉取线程只执行一次就结束了。因为抽象的拉取线程类继承了ShutdownableThread,而后者继承了Thread类,它的run方法会循环调用抽象的doWork()方法,所以ShutdownableThread的实现类(比如抽象的拉取线程类和LeaderFinderThread)在doWork()方法中不需妥考虑线程循环运行的问题。

拉取钱程每i用用一次doWork(),都会根据partitionMap构建并发送拉取请求。在拉取到消息之后、处理拉取结果之前,要更新part1tionMap中所有分区的拉取状态。part1tionMap一旦发生变化,依赖于part1tionMap的拉取请求就必须重新构建。那么part1tionMap拉取状态的变化对拉取请求有什么影响呢?

再平衡操作为消费者重新分配新的分区,有些分区可能之前并不属于当前消费者。在消费者拉取线程第一次拉取分区的消息时,需要从ZK读取分区的拉取状态(即偏移量),作为第一次拉取请求的拍取偏移盘。比如,Pl原先被分配给消费者l,经过一次再平衡后被分配给消费者2。消费者2的拉取线程开始工作时,需要从ZK中读取Pl的偏移量,作为第一次拉取请求的Pl拉取状态。后续的拉取请求如果没有发生再平衡操作,则可以直接从part1tionMap中获取Pl分区的拉取状态。每个拉取线程都在自己本地保存了当前负责所有分区的拉取状态,拉取线程每次在收到拉取请求的响应结果后,会用本次拉取消息集最后一条消息的偏移量来更新part1tionMap,下一次会从上一次拉取的最后一个位置继续拉取。这样就可以保证拉取线程的每一次拉取请求总是拉取新的消息集,而且不会重复。所以,除了第一次拉取请求获取拉取状态是从ZK读取,后面的拉取请求都直接从part1tionMap中读取。

注意:由于partitionMap拉取状态只是拉取线程中的内存数据结构,如果拉取线希呈挂了,分区的消费状态就会丢失,所以客户端需要定时地保存消费状态。对于消费者客户端,通过开启autoCornmit开关,定时提交分区的偏移量到ZK中;对于备份副本,则会将偏移量写到本地的检查点文件中。

抽象拉取线程的运行方法中定义了构建拉取请求、拉取消息、处理拉取结果的接口,下面我们来看消费者拉取线程对这3个接口方法的具体实现。


相关推荐
<p> <span style="font-size:14px;color:#E53333;">限时福利1:</span><span style="font-size:14px;">购课进答疑群专享柳峰(刘运强)老师答疑服务</span> </p> <p> <br /> </p> <p> <br /> </p> <p> <span style="font-size:14px;"></span> </p> <p> <span style="font-size:14px;color:#337FE5;"><strong>为什么需要掌握高性能的MySQL实战?</strong></span> </p> <p> <span><span style="font-size:14px;"><br /> </span></span> <span style="font-size:14px;">由于互联网产品用户量大、高并发请求场景多,因此对MySQL的性能、可用性、扩展性都提出了很高的要求。使用MySQL解决大量数据以及高并发请求已经是程序员的必备技能,也是衡量一个程序员能力和薪资的标准之一。</span> </p> <p> <br /> </p> <p> <span style="font-size:14px;">为了让大家快速系统了解高性能MySQL核心知识全貌,我为你总结了</span><span style="font-size:14px;">「高性能 MySQL 知识框架图」</span><span style="font-size:14px;">,帮你梳理学习重点,建议收藏!</span> </p> <p> <br /> </p> <p> <img alt="" src="https://img-bss.csdnimg.cn/202006031401338860.png" /> </p> <p> <br /> </p> <p> <span style="font-size:14px;color:#337FE5;"><strong>【课程设计】</strong></span> </p> <p> <span style="font-size:14px;"><br /> </span> </p> <p> <span style="font-size:14px;">课程分为四大篇章,将为你建立完整的 MySQL 知识体系,同时将重点讲解 MySQL 底层运行原理、数据库的性能调优、高并发、海量业务处理、面试解析等。</span> </p> <p> <span style="font-size:14px;"><br /> </span> </p> <p> <span style="font-size:14px;"></span> </p> <p style="text-align:justify;"> <span style="font-size:14px;"><strong>一、性能优化篇:</strong></span> </p> <p style="text-align:justify;"> <span style="font-size:14px;">主要包括经典 MySQL 问题剖析、索引底层原理和事务与锁机制。通过深入理解 MySQL 的索引结构 B+Tree ,学员能够从根本上弄懂为什么有些 SQL 走索引、有些不走索引,从而彻底掌握索引的使用和优化技巧,能够避开很多实战中遇到的“坑”。</span> </p> <p style="text-align:justify;"> <br /> </p> <p style="text-align:justify;"> <span style="font-size:14px;"><strong>二、MySQL 8.0新特性篇:</strong></span> </p> <p style="text-align:justify;"> <span style="font-size:14px;">主要包括窗口函数和通用表表达式。企业中的许多报表统计需求,如果不采用窗口函数,用普通的 SQL 语句是很难实现的。</span> </p> <p style="text-align:justify;"> <br /> </p> <p style="text-align:justify;"> <span style="font-size:14px;"><strong>三、高性能架构篇:</strong></span> </p> <p style="text-align:justify;"> <span style="font-size:14px;">主要包括主从复制和读写分离。在企业的生产环境中,很少采用单台MySQL节点的情况,因为一旦单个节点发生故障,整个系统都不可用,后果往往不堪设想,因此掌握高可用架构的实现是非常有必要的。</span> </p> <p style="text-align:justify;"> <br /> </p> <p style="text-align:justify;"> <span style="font-size:14px;"><strong>四、面试篇:</strong></span> </p> <p style="text-align:justify;"> <span style="font-size:14px;">程序员获得工作的第一步,就是高效的准备面试,面试篇主要从知识点回顾总结的角度出发,结合程序员面试高频MySQL问题精讲精练,帮助程序员吊打面试官,获得心仪的工作机会。</span> </p>
©️2020 CSDN 皮肤主题: 酷酷鲨 设计师:CSDN官方博客 返回首页