再见,ELK( 三 )


  • Instances:以租户的 userID 为键 Instance 为值的 Map 结构 。
  • Instance:一个租户下所有日志流(stream)的容器 。
  • Streams:以日志流的指纹(streamFP)为键 , Stream 为值的 Map 结构 。
  • Stream:一个日志流所有 Chunk 的容器 。
  • Chunks:Chunk 的列表 。
  • Chunk:持久存储读写最小单元在内存态的结构 。
  • Block:Chunk 的分块 , 为已压缩归档的数据 。
  • HeadBlock:尚在开放写入的分块 。
  • Entry:单条日志单元 , 包含时间戳(timestamp)和日志内容(line)
整体结构如下:
再见,ELK

文章插图
 
Chunks:在向内存写入数据前 , ingester 首先会根据租户ID(userID)和由标签计算的指纹(streamPF)定位到日志流(stream)及 Chunks 。
Chunks 由按时间升序排列的 chunk 组成 , 最后一个 chunk 接收最新写入的数据 , 其他则等刷写到底层存储 。
当最后一个 chunk 的存活时间或数据大小超过指定阈值时 , Chunks 尾部追加新的 chunk。
Chunk:Chunk 为 Loki 在底层存储上读写的最小单元在内存态下的结构 。其由若干 block 组成 , 其中 headBlock 为正在开放写入的 block  , 而其他 Block 则已经归档压缩的数据 。
Block:Block 为数据的压缩单元 , 目的是为了在读取操作那里避免因为每次解压整个 Chunk 而浪费计算资源 , 因为很多情况下是读取一个 chunk 的部分数据就满足所需数据量而返回结果了 。
Block 存储的是日志的压缩数据 , 其结构为按时间顺序的日志时间戳和原始内容 , 压缩可采用 gzip、snAppy 、lz4 等方式 。
HeadBlock:正在接收写入的特殊 block  , 它在满足一定大小后会被压缩归档为 Block  , 然后新 headBlock 会被创建 。
存储适配:由于底层存储要支持 S3、Cassandra、BigTable、DnyamoDB 等系统 , 适配层将各种系统的读写操作抽象成统一接口 , 负责与他们进行数据交互 。
④输出
Loki 以 Chunk 为单位在存储系统中读写数据 。在持久存储态下的 Chunk 具有如下结构:
  • meta:封装 chunk 所属 stream 的指纹、租户 ID , 开始截止时间等元信息 。
  • data:封装日志内容 , 其中一些重要字段 。
  • encode 保存数据的压缩方式 。
  • block-N bytes 保存一个 block 的日志数据 。
  • #blocks section byte offset 单元记录 #block 单元的偏移量 。
  • #block 单元记录一共有多少个 block 。
  • #entries 和 block-N bytes 一一对应 , 记录每个 block 里有日式行数、时间起始点 , blokc-N bytes 的开始位置和长度等元信息 。

再见,ELK

文章插图
 
Chunk 数据的解析顺序:
  • 根据尾部的 #blocks section byte offset 单元得到 #block 单元的位置 。
  • 根据 #block 单元记录得出 chunk 里 block 数量 。
  • 从 #block 单元所在位置开始读取所有 block 的 entries、mint、maxt、offset、len 等元信息 。
  • 顺序的根据每个 block 元信息解析出 block 的数据 。
⑤索引
Loki 只索引了标签数据 , 用于实现标签→日志流→Chunk 的索引映射 ,  以分表形式在存储层存储 。
表结构如下:
CREATE TABLE IF NOT EXISTS Table_N (hash text,range blob,value blob,PRIMARY KEY (hash, range)) Table_N , 根据时间周期分表名;hash ,  不同查询类型时使用的索引;range , 范围查询字段;value , 日志标签的值 。
数据类型:Loki 保存了不同类型的索引数据用以实现不同映射场景 , 对于每种类型的映射数据 , Hash/Range/Value 三个字段的数据组成如下图所示:
再见,ELK

文章插图
 
seriesID 为日志流 ID , shard 为分片 , userID 为租户 ID , labelName 为标签名 , labelValueHash 为标签值 hash , chunkID 为 chunk 的 ID , chunkThrough 为 chunk 里最后一条数据的时间这些数据元素在映射过程中的作用在 Querier 环节的[查询流程]((null))做详细介绍 。
上图中三种颜色标识的索引类型从上到下分别为: