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内核也有个内存池.内存池的存在主要就是减 ...
随机推荐
- Centos7 开启端口
CentOS7默认没有使用iptables,所以通过编辑iptables的配置文件来开启80端口是不可以的. CentOS 7 采用了 firewalld 防火墙. 如要查询是否开启80端口: [ro ...
- offsetTop、offsetLeft、offsetWidth、offsetHeight的用法
假设 obj 为某个 HTML 控件. obj.offsetTop 指 obj 相对于版面或由 offsetParent 属性指定的父坐标的计算上侧位置,整型,单位像素. obj.offsetLeft ...
- SAP HANA项目过程中优化分析以及可行性验证
在项目开发过程中,经常会遇到HANA模型运行效率的问题: 以我们项目为例,HANA平台要求模型运行时间不能超过10秒,但是在大数量和计算逻辑复杂的情况下(例如:ERP中的BKPF和BSEG量表的年数据 ...
- ffplay源码分析7-播放控制
本文为作者原创,转载请注明出处:https://www.cnblogs.com/leisure_chn/p/10316225.html ffplay是FFmpeg工程自带的简单播放器,使用FFmpeg ...
- What is AMQP? and the architecture
What is AMQP? (Advanced Message Queuing Protocol) When two applications need to communicate there ar ...
- Nginx初探
nginx是一款轻量级的web服务器.反向代理服务器和电子邮件服务器,占有内存少,并发能力强. 本文将简单介绍如何安装.启动nginx,部署web项目,应用反向代理. 一.安装 可参考https:// ...
- MyCat安装配置
Mycat : 数据库分库分表中间件 http://www.mycat.io/ mycat运行需要JVM,所以先安装java环境,JDK1.7以上.数据库采用mysql5.7,或者8.0 下载 下载地 ...
- MySQL5.7 常用用户操作
目录 MySQL5.7 常用用户操作 1. 新建用户 2. 授权 3. 创建用户时授权 4. 设置与更改用户密码(root) 5. 撤销用户权限 6. 删除用户 7. 查看用户的授权 8. 显示当前用 ...
- Java - "JUC" ReentrantReadWriteLock
Java多线程系列--“JUC锁”08之 共享锁和ReentrantReadWriteLock ReadWriteLock 和 ReentrantReadWriteLock介绍 ReadWriteLo ...
- Hanoi问题 算法
问题描述:假设有3个分别命名为A.B.C的塔座,在塔座A上插有n个直径大小各不同,一小到大标号为1,2,….,n的圆盘,要求将塔座A上的n个圆盘移动到C盘上,并且仍按原来的顺序叠排. 同时遵循下列规则 ...