leveldb源码分析--日志
我们知道在一个数据库系统中为了保证数据的可靠性,我们都会记录对系统的操作日志。日志的功能就是用来在系统down掉的时候对数据进行恢复,所以日志系统对一个要求可靠性的存储系统是极其重要的。接下来我们分析leveldb的日志,首先在leveldb源码目录中有doc/log_format.txt,这个文件详细的描述了leveldb的日志格式:
record :=
checksum: uint32 // crc32c of type and data[] ; little-endian
length: uint16 // little-endian
type: uint8 // One of FULL,FIRST, MIDDLE, LAST
data: uint8[length]
如下图(图片引用):
leveldb在写日志时,对日志文件进行了划分为多个32K的文件块,每次读写日志时都以这样的每个32K为单位。这样进行处理以后leveldb的日志文件的大致组成就可以看做为如下的形式:
那么我们初步描述一下Log的写入情况为:
当要写入一条首先判断当前block中是否足够存放该条日志
S1.如果足够那么直接安装格式写入;
S2.如果不够那么计算出去头以外可以存放多少内容,将内容组装为FIRST的Log typpe写入;然后新取一个块判断是否足够存放剩下的日志数据
while(数据未写完)
S21. 如果足够就组装为LAST的形式写入;
S22. 如果仍然不够就组装为MIDDLE的形式写入
所以就容易理解这里的FULL,FIRST,MIDDLE和LAST了:
FULL:一条完整的日志被写到block
FIRST:一条日志,但是当前block无法完全写入,有部分数据被写到了下一个block,当前block的数据只是日志的开始(第一)部分
MIDDLE:该日志内容是接着前一个block里面的最后一条日志的继续,而且本block还无法完全写完,在下一个block中继续有该条日志的数据
LAST: 之前block的未写完的日志的最后一部分;
另外需要注意的就是根据前面的描述我们可以想象得到一个block在写入一部分数据以后会剩下部分空间,这个空间可能是大于7byte,等于7byte,小于7byte;这里为什么要以7byte为分界呢?日志记录的header(crc|length|type)长度为7,如果超过7就至少可以存一个FISRT的部分日志记录,而等于7就刚好存一个header,少于7就连header都存不了。LOG也正是基于这样的原因,小于7时就补充”\0”,7就存一个空header。我们来看看代码逻辑
Status Writer::AddRecord(const Slice& slice) {
bool begin = true;
// 循环向日志文件写,直到写完为止
do {
const int leftover = kBlockSize - block_offset_;
if (leftover < kHeaderSize) {// 小于 7 byte (header size )填充 0x0
if (leftover > ) {
dest_->Append(Slice("\x00\x00\x00\x00\x00\x00", leftover));
}
block_offset_ = ;
}
const size_t avail = kBlockSize - block_offset_ - kHeaderSize;
const size_t fragment_length = (left < avail) ? left : avail;
RecordType type;
const bool end = (left == fragment_length);{// 判断本段能否写完
if (begin && end) { // 开始结束都在本block
type = kFullType;
} else if (begin) { // 开始在本block,结束不在
type = kFirstType;
} else if (end) { // 结束在,开始不在
type = kLastType;
} else { // 开始结束都不在本block
type = kMiddleType;
}
// encode 然后再写入文件中
s = EmitPhysicalRecord(type, ptr, fragment_length);
ptr += fragment_length;
left -= fragment_length;
begin = false;
} while (s.ok() && left > );
return s;
}
读日志的代码在log_reader.cc中,代码的逻辑比写负责很多,主要是读入时会需要增加很多错误处理相关的内容,具体的代码不在罗列,理解了日志文件的格式以后的很容易就能读懂。当然同时其异常处理的逻辑也是我们码农们学习的材料,理解一下高手们是如何进行各种错误处理的。
leveldb源码分析--日志的更多相关文章
- leveldb源码分析--WriteBatch
从[leveldb源码分析--插入删除流程]和WriteBatch其名我们就很轻易的知道,这个是leveldb内部的一个批量写的结构,在leveldb为了提高插入和删除的效率,在其插入过程中都采用了批 ...
- leveldb源码分析--SSTable之block
在SSTable中主要存储数据的地方是data block,block_builder就是这个专门进行block的组织的地方,我们来详细看看其中的内容,其主要有Add,Finish和CurrentSi ...
- leveldb源码分析--Key结构
[注]本文参考了sparkliang的专栏的Leveldb源码分析--3并进行了一定的重组和排版 经过上一篇文章的分析我们队leveldb的插入流程有了一定的认识,而该文设计最多的又是Batch的概念 ...
- Leveldb源码分析--1
coming from http://blog.csdn.net/sparkliang/article/details/8567602 [前言:看了一点oceanbase,没有意志力继续坚持下去了,暂 ...
- 精尽Spring Boot源码分析 - 日志系统
该系列文章是笔者在学习 Spring Boot 过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring Boot 源码分析 GitHub 地址 进行阅读 Sprin ...
- leveldb源码分析之Slice
转自:http://luodw.cc/2015/10/15/leveldb-02/ leveldb和redis这样的优秀开源框架都没有使用C++自带的字符串string,redis自己写了个sds,l ...
- LevelDB源码分析--Cache及Get查找流程
本打算接下来分析version相关的概念,但是在准备的过程中看到了VersionSet的table_cache_这个变量才想起还有这样一个模块尚未分析,经过权衡觉得leveldb的version相对C ...
- leveldb源码分析--SSTable之TableBuilder
上一篇文章讲述了SSTable的格式以后,本文结合源码解析SSTable是如何生成的. void TableBuilder::Add(const Slice& key, const Slice ...
- leveldb源码分析之内存池Arena
转自:http://luodw.cc/2015/10/15/leveldb-04/ 这篇博客主要讲解下leveldb内存池,内存池很多地方都有用到,像linux内核也有个内存池.内存池的存在主要就是减 ...
随机推荐
- 设置ListView显示到最后一行
上次聊天的那个界面上用的一个TextView,然后每次消息都用text.append("消息内容"+"\n")函数来在text字符串后边接一段,然后重新显示这个 ...
- 02-04:springboot 访问静态资源
1.SpringBoot从classpath/static的目录下:(目录名称必须叫static,可以理解为根目录为static) 2.servletContext根目录下,进行查找: 在src/ma ...
- iOS Round Double value to 2 decimal digits and round 3rd decimal digit up
I have I double value like this one 17.125. It should be rounded up to 17.13 If I use the simple met ...
- 【转载】配置文件报错:不允许有匹配 [xX][mM][lL] 的处理指令目标
今天编写代码的时候,不小心给一个xml文件的首行加了一行空格,导致了启动报了如题类似的错误,查到一篇文章,顺藤摸瓜发现了这个失误,文章转载如下: 框架整合 的时候,XML 配置文件大多数情况是从另一个 ...
- elasticSearch6源码分析(3)cluster模块
1. cluser概述 One of the main roles of the master is to decide which shards to allocate to which nodes ...
- 【Vue.js实战案例】- Vue.js递归组件实现组织架构树和选人功能
大家好!先上图看看本次案例的整体效果. 浪奔,浪流,万里涛涛江水永不休.如果在jq时代来实这个功能简直有些噩梦了,但是自从前端思想发展到现在的以MVVM为主流的大背景下,来实现一个这样繁杂的功能简直不 ...
- Linux后台运行java的jar包
Linux 运行jar包命令如下: 方式一 特点:当前ssh窗口被锁定,可按CTRL + C打断程序运行,或直接关闭窗口,程序退出 那如何让窗口不锁定? 方式二 java -jar shareniu. ...
- [转]Build beautiful, responsive sites with Bootstrap and ASP.NET Core
本文转自:https://docs.microsoft.com/en-us/aspnet/core/client-side/bootstrap?view=aspnetcore-2.1 Bootstra ...
- DataGridview启用列重新排序属性的作用
DataGridview是winform中经常用的控件,今天来了解一下启用列重新排序属性的作用 默认没有选中是不能改变列前后顺序的 启用列重新排序后如下图可以拖动列标题(列标头)来改变列前后顺序
- glob 在webpack中的使用。
glob 在webpack中对文件的路径处理非常之方便,比如当搭建多页面应用时就可以使用glob对页面需要打包文件的路径进行很好的处理. 官方文档地址 : https://www.npmjs.com/ ...