Page 90 - 《软件学报》2021年第5期
P. 90
1314 Journal of Software 软件学报 Vol.32, No.5, May 2021
LogView←decompress(data) //解压缩
return LogView
end function
索引查询的过程如下.
(1) 首先,根据 LogView 的 id 值解析出 ip 地址,再根据日志上报的路由信息、{hour}数据和应用名信息定
位到该日志存在哪台机器上哪个文件目录下,以及对应的索引文件和数据文件.此外,根据 id 获取到
index 值,并拼接 ip 与 index/4K 的值为 A.
(2) 遍历一级索引中所有的 Entry,找到与 A 值相等的一级 Entry 值,即可定位到对应的二级 Segment 索引.
(3) 根据 index%4K 的值定位到二级索引中的 Entry 位置,获取对应 Entry 中的数据,即可分析得到该
LogView 存放的内存块的首地址以及块内偏移量.
(4) 根据内存块首地址(headAddress)获取首部 4 个字节的数据,得到内存块具体的字节大小(blockSize),将
指定字节量大小的块加载到内存中,再根据偏移量位置(offset)及后续 4 字节的长度信息(logSize),获取
指定的长度字节数据后经过解压缩即可得到对应 LogView 的原日志数据.
3.4 磁盘空间管理
在索引文件存储的时候,一级索引的空间会全部创建,而二级索引只会在新建一级索引 Entry 值时才会创
建.如图 8 所示,以 ip1,index(0~8K−1)为例,对应会创建两个一级索引 Entry 值,即“ip1,0”与“ip1,1”.一级索引中条
目 Entry 值为“ip1,0”对应的 index 范围为(0~4K−1),根据 index%4K 的值,刚好与对应的二级索引 Entry 值一一对
应,刚好占据 4K 个 Entry 值.“ip1,1”对应所有 LogView 的 index 范围为(4K~8K−1),而每个 LogView 根据
index%4K 的值刚好与图中第 2 个 Segment 索引中 4K 个 Entry 一一对应.以 ip2,index(0~3K−1)为例,占据了一级
索引的第 4 个 Entry,且对应的二级索引中实际只占据了 3K 个 Entry 的空间.
Fig.8 Memory usage of two-level indexing
图 8 两级索引的内存占用
总的来说,上述例子中来自 ip1 与 ip2 所有的日志数据在索引文件中仅占据了 128KB(4K×8+4K×8×3)的大
小.二级索引的 Entry 值是按顺序存放的,顺序写数据的性能很高;此外,二级索引中不存在空洞空间,即不存在内
存碎片,并且二级索引空间是在需要的时候才开辟,这些都可以有效的节省磁盘空间.
3.5 特殊情况处理
前面说明了正常情况下的日志数据存储与查询流程,下面对几种特殊情况发生后的处理方式作出说明.
(1) 读写冲突
在内存块写入数据文件时,如果此时有日志查询的请求到来,并且该条请求日志也正好在这部分内存块中,
此时同时写和读数据文件时,理论上存储冲突.所以日志存储与查询的流程设计如下.
• 首先查询内存空间,如果存在,则直接从内存中返回日志数据;
• 如果不存在,则到磁盘文件中查找.