3.6.3 获取分区的读取偏移量


3.6.3 获取分区的读取偏移量

读取分区的偏移量涉及日志存储,这里我们先给出一些简单的结论(具体细节会在第6章详细分析):一个分区有多个片段文件(Segment),每个片段文件都包含全局有序的片段基准偏移量(segmentBaseOffset)。客户端调用getlastOffset()获取的是每个片段文件的基准偏移量。

客户端发送的偏移毡’请求(OffsetRequest)包含的数据是:分区偏移量的请求信息(PartitionOffsetinfo)。这个对象有两个参数:whichTime表示拉取的时间戳,默认第一次拉取的时间戳为EarliestTime=-2,如果拉取响应的错误码是OffsetOutofRange,则时间戳设置为LatestTime=-1;maxNuMOffsets表示需要获取多少个片段文件的基准偏移量,消费者获取最近的偏移量通常只需要一个偏移盘值,所以第二个参数值为1。相关代码如下:
在这里插入图片描述
消费者发送的偏移量请求类型是LIST_OFFSETS,服务端使用handleOffsetRequest()处理请求,并返回分区的偏移量集合。存储消息时除了存储消息内容本身,还会存储消息对应的偏移盏,但Li.stOffsets并不是要返回所有消息的偏移量,而是每个片段文件的基准偏移量。一个分区的片段文件数量并不会很多,相比有多少条消息就返回多少个偏移盘,后者的数据盘传输更少且更快。

消费者读取分区的偏移虽有一个限制条件:不能超过服务端中这个分区的最高水位(HighWatermark,下文简称HW)。服务端只能保证HW之前的消息已经提交,而HW之后的消息没有提交。fetchOffsets()返回的是按照偏移量降序排列的数组,如果偏移量比HW大,则会被丢弃。相关代码如下:
在这里插入图片描述
fetchOffsetsBefore()方法获取指定时间戳之前的偏移量,最后返回的是片段文件对应的基准偏移量。每个片段文件对应一个基准偏移盘,startindex表示片段文件的索引编号。读取片段文件跟重置策略有关,如果重置策略是最早(EARLIEST_TImESTAmP),IQiJstart!ndex置为O(即第一个片段文件);如果是最近(LATEST_TImESTAmP),则是最后一个片段文件的索引编号。

offsetTimeArray数组会按照时间戳的升序,存储所有片段文件的基准偏移量和最近修改的时间,这个修改时间就是用来和时间戳参数比较的依据:要返回指定时间戳之前的偏移盘,应该从后面的片段文件开始往前推;如果片段文件的最近修改时间比指定的时间戳小,贝iJ设置start!ndex为当前找到的片段文件。

片段文件的偏移盘和时间戳是成正比增加的。为了简单起见,假设时间戳和偏移量是等价的,并假设我们要获取时间戳为12之前的3个偏移盘。首先找到小于时间戳的最大值是l1,startindex就是位置ll,然后再往前找3个,假设allOffsets为[11,8,5],并且hw为10,则hw+:allOffsetsdropWhile(>hw)的结果为List(l0,8,5)。相关代码如下:
在这里插入图片描述
注意:dropWhile的含义是将大于hw的删掉。因为allOffsets是降序排列,如果allOffsets中第一个元素就比hw小,就不会丢弃任何元素,比如10+:List(8,5).dropWhile(
>10)=List(10,8,5)。如果allOffsets中最小的都比hw要大,最后就只有hw,比如10+:Li.st(20,17,14).dropWhile(_>10)=List(10)。

客户端有了分区,而且也知道要从分区的什么位置开始读取消息,接下来就是向分区的主副本节点发送拉II~:请求以得到消息。


相关推荐
©️2020 CSDN 皮肤主题: 酷酷鲨 设计师:CSDN官方博客 返回首页