暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Grafana Tempo源码解读(六)Compactor的代码结构和同步Block过程

栋总侃技术 2023-12-23
168

在阅读查询过程的代码时,许多操作与Block的处理有关。如果对于Tempo如何将Block进行压缩和删除逻辑不理解,无法理解其中的查询逻辑。所以本节先对Tempo Compactor组件的代码进行阅读讲解,了解Compactor的结构和其同步Block的过程,为了解其如何对Block进行压缩和删除的逻辑做铺垫。

类关系图谱


Compactor模块只依赖Store模块。所以Compactor所有的操作都是依赖storage.Store对象完成。在上面结构图里着重体现的也是storage.Store的组成。

storage.Store结构中有三个重要的对象完成Compactor的压缩和清理过程,分别是tempodb.Reader
tempodb.Writer
tempodb.Compactor

这三个对象都是由tempodb.readerWriter
定义,且是一个共有的对象。在tempodb.readerWriter
中定义了:

  • 负责从对象存储读取Block的r backend.Reader

  • 负责对对象存储的Block进行删除或者压缩后写入操作的w backend.Writer

  • 负责执行对哪些Block进行压缩、确定哪些Block可以删除的逻辑操作c backend.Compactor

blocklistPoller *blocklist.Poller

负责周期性的通过reader遍历所有的Block,并写入blocklist *blocklist.List
,在blocklist中维护了两个结构metas
compactedMetas
。从对象存储中读取到的Block如果没有被压缩就会被添加至metas
,对metas进行压缩后会写入compactedMetas

以上就是Compactor组件运行过程中所依赖的结构的层级关系,以及各对象的职责划分。

EnablePolling

在Compactor组件的starting函数里会调用store.EnablePolling
开启定时从存储中同步Blocks。如果不开启compactor(不建议在生产环境使用),则不会执行该操作。

程序启动后会直接开始同步Blocks,同时会根据配置blocklist_poll
(默认5分钟)的时间定时同步。

通过block的父目录可以获取到有哪些租户,遍历每个租户同步租户的blockList。

pollTenantBlocks

获取currentBlockIDs, currentCompactedBlockIDs

通过遍历对象存储中租户下的目录获取blockID列表,已经根据该目录下存在meta.json文件还是meta.compacted.json文件确定将blockappend至blockIDs、compactedBlockIDs。返回赋值给currentBlockIDs
,currentCompactedBlockIDs

previous *List

由于pollTenantBlocks会周期性的调用,previous中存放了最近一次同步、或者处理后的结果,其结构如下,其中每个属性都在后续的逻辑处理中有重要的作用,已添加注释说明:

// PerTenant is a map of tenant ids to backend.BlockMetas
type PerTenant map[string][]*backend.BlockMeta

// PerTenantCompacted is a map of tenant ids to backend.CompactedBlockMetas
type PerTenantCompacted map[string][]*backend.CompactedBlockMeta

type List struct {
  mtx            sync.Mutex
  metas          PerTenant   当前租户的Blocks
  compactedMetas PerTenantCompacted   当前租户的compactedBlocks

  // used by the compactor to track local changes it is aware of
  added            PerTenant    新添加的Blocks
  removed          PerTenant    转化为compactedBlocks的Blocks
  compactedAdded   PerTenantCompacted // 新添加的Blocks compactedBlocks
  compactedRemoved PerTenantCompacted // 达到保留时间,待删除的compactedBlocks
}

c backend.Compactor
负责执行对哪些Block进行压缩、确定哪些Block可以删除的逻辑操作,最终对List上述的各个成员属性进行动态维护。

previous确定newBlockList、newCompactedBlocklist、unknownBlockIDs

遍历获取到的currentBlockIDs,如果在previous.meta里,添加至newBlockList,如果不在previous.meta里,则设置unknownBlockIDs[blockID] = false
(这里的false表示这时候可以确定这个block是要添加至List.metas属性里的)

遍历获取到的currentCompactedBlockIDs,如果在previous.compactedMetas里,则添加至newCompactedBlocklist,如果不在,那么就没法确定其真实状态了,设置unknownBlockIDs[blockID] = true

pollUnknown 确定unknownBlockIDs的真实身份
  • 如果为false(还不确定身份),再次从对象存储里面读取是否存在meta.json。

  • 如果不存在,那么或许是在之前的处理步骤中异常了,根据当前block的内容重新渲染meta.compacted.json文件并返回:

从对象存储里面读取Blocks时是根据配置blocklist_poll_concurrency
(默认50)并发获取Blocks,boundedwaitgroup通过channel实现最多支持多少个并发同时进行,超过并发的阻塞等待。

bg = boundedwaitgroup.New(p.cfg.PollConcurrency)

最终确定blocks是属于newBlockList
,还是newCompactedBlocklist

最后将最新的newBlockList
newCompactedBlocklist
按照StartTime进行排序后返回。

ApplyPollResults 维护List的各个成员

newBlockList
newCompactedBlocklist
赋值给metas
compactedMetas
.

ApplyPollResults 函数在对Block进行压缩处理后也会调用,所以这里有更新l.added, l.removed, l.compactedAdded, l.compactedRemoved。在上述同步Blocks的过程中没有对这些属性的处理过程,我们暂且认为这些参数为空,在后面对Block压缩的过程再进行讲解。

到这里完成了Compactor组件中各Go结构体(类)的定义和关系和Compactor组件如何同步Block的源码解读。下一节将继续对Compactor组件的源码进行讲解,了解Compactor组件对同步的Block是如何进行压缩、清理处理的。

往期回顾:

Grafana Tempo源码解读(五)总结Tempo接收数据的限制以及配置调整

Grafana Tempo源码解读(四)Ingester组件将数据写入持久化存储

Grafana Tempo源码解读(三)Ingester组件接收Trace数据的过程

Grafana Tempo源码解读(二)Distributor对Trace数据的处理和发送至Ingester

Grafana Tempo源码解读(一)Distributor建立监听接收Trace数据




文章转载自栋总侃技术,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论