leveldb的sstable-ldb解析
(Owed by: 春夜喜雨 http://blog.csdn.net/chunyexiyu)
leveldb数据库的sstable-ldb文件解析。
引言
ldb文件作为sorted-string-table,是一个自成体系的单数据库文件,自身就包含了排序索引信息,以及相应的key,value信息;
基于该文件结构可以快速检索到查询的key数据,获取相关value数据。
ldb的解析过程,通常情况,不涉及定制compare与指定filter的情况下,涉及的过程为:
解析Footer–>解析index block->解析data block.
解析Footer–>通过metablock指向解析可选filter block
下面尝试解析一个只有一条数据的ldb文件:
(文档最后来揭晓放入的该条KV值)
$ xxd 000005.ldb
00000000: 0010 1030 3030 3030 3030 3001 0100 0000 ...00000000.....
00000010: 0000 0061 6161 6161 6161 6161 6161 6161 ...aaaaaaaaaaaaa
00000020: 6161 6100 0000 0001 0000 0000 59f3 a005 aaa.........Y...
00000030: 0000 0000 0100 0000 00c0 f2a1 b000 0902 ................
00000040: 3101 ffff ffff ffff ff00 2b00 0000 0001 1.........+.....
00000050: 0000 0000 099d d7b9 3008 3d16 0000 0000 ........0.=.....
00000060: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000070: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000080: 57fb 808b 2475 47db W...$uG.
1. footer
对于Footer内容,ldb文件的后48字节是Footer,也就是ldb解析时最早解析的内容:
$ xxd -u -s -48 000005.ldb
00000058: 3008 3D16 0000 0000 0000 0000 0000 0000 0.=.............
00000068: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000078: 0000 0000 0000 0000 57FB 808B 2475 47DB ........W...$uG.
- Footer内容读取
Footer-48位中,最后8字节是magic-number,是固定值,要求对应
unsigned char magic[8] = {0x57, 0xFB, 0x80, 0x8B, 0x24, 0x75, 0x47, 0xDB};Footer-48位中,前40位打包了两个BlockHandle,每个handle存两个64位的unsigned类型
uint64_t metaIndex.offset, metaIndex.size;
uint64_t index.offset, index.size;
使用的7bits变长方式存储的,所以实际使用长度通常都是远小于40字节的,每个字节开头字母小于8的,是结束符。Footer码流样例前40个字节解析:
footer: magic number 57FB 808B 2475 47DB
footer: meta.offset-0x30, meta.size-0x08, index.offset-0x3D, index.size-0x16
(十进制: meta.offset-48, meta.size-8, index.offset-61, index.size-22)
2. Index Block内容读取校验
block存储到文件内容:block.size + trailer(5字节)代表block存储到文件的总内容;
基于上面的头信息获取到的index.offset,index.size值截取码流
$ xxd -u -s 61 -l 27 000005.ldb
0000003d: 0009 0231 01FF FFFF FFFF FFFF 002B 0000 ...1.........+..
0000004d: 0000 0100 0000 0009 9DD7 B9 ...........
- Trailer: 码流0x00 09 9D D7 B9
trailer[0]:trailer里面的第一个字节,存储了是否采用压缩,采用何种压缩;有压缩时,后续使用block内容时就要解压缩了。
trailer[1-4]:trailer里面的后4个字节,存储了block.size+trailter[0]的crc校验码;ReadOption中的参数决定了是否校验一下。 - Block:
- block[size-4, size): 存储numRestarts,码流0x01 00 00 00,numRestarts值为1
- block[size-numRestarts*4-4, size-4):存储restart offset array. 码流0x00 00 00 00,restart offset值为0.
- block[0, size-numRestarts*4-4):存储Entries(key/value)值,下面是一个Entry解析
- Entry: (key<128位时)
entry[0]-key shared length
entry[1]-key none shared length
entry[2]-value length
entry[3, 3+entry[1]+entry[2])-none shared key, value
entry-key: 存的是block最后一个键值
entry-value: 存的是block的handle,也就是存了block.offset, block.size,同样是使用7bits变长存储的indexblock样例解析结果:
index block: compress-0, crc-0xB9D79D09, restartnums-1
index block: restart0, shared-0, nonshared-9, valuelen-2, key-0x31 01 FF FF FF FF FF FF FF , value=0x00 2B
value解析:bock.offset=0x00, block.size=0x2B
3. data block内容读取
通过index block的entry-value,锁定了data block的offset和size,这样就能基于此来读取datablock了。
data block的结构与index block结构一致,也是先读trailer,然后读取numRestarts,然后是Entry,不过这次Entry-value存的[(key,value)…]块。
datablock码流样例:
bock.offset=0x00, block.size=0x2B,尾部trailer长度5,长度共计43+5=48
$ xxd -u -s 0 -l 48 db1/000005.ldb
00000000: 0010 1030 3030 3030 3030 3001 0100 0000 ...00000000.....
00000010: 0000 0061 6161 6161 6161 6161 6161 6161 ...aaaaaaaaaaaaa
00000020: 6161 6100 0000 0001 0000 0000 59F3 A005 aaa.........Y...
下面是index-block指向的第一个datablock内容:
data block: offset, size-43, compress-0, crc-0x05a0f359, restartnums-1
data block: shared-0, nonshared-16, valuelen-16, key-0x30 30 30 30 30 30 30 30 01 01 00 00 00 00 00 00 , value=0x61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61
4. meta block解析
因为没有使用到filter,meta-block内容中,当前的内容指向为空
meta.offset-0x30, meta.size-0x08, 加上block-trailer的5个字节,共计使用13字节。
00000030: 0000 0000 0100 0000 00c0 f2a1 b0
Block:
+ block[4, 8): 存储numRestarts,码流0x01 00 00 00,numRestarts值为1
+ block[0, 4):存储restart offset array. 码流0x00 00 00 00,restart offset值为0.
5. 从代码角度看写入次序
从上面可以看到基于尾部footer找出metablock/indexblock,然后再索引到datablock。
那实际写入时,是metablock在前,还是indexblock在前?
这块可以基于TableBuilder::Finish代码实现找出来。
SortedStringTable开始的DataBlock数据是:
{DataBlock+Tailer; DataBlock+Tailer; DataBlock+Tailer;…}
StringSortedTable之后的索引等尾部数据次序是:
- 有filter时:写入无压缩的FilterBlock+Tailer
- 写入MetaIndexBlock+Tailer
- 写入IndexBlock+Tailer
- 写入Footer
6. ldb放入的KV值
最后,公布这个000005.ldb中实际放入的KV值如下:
放入ldb的该条记录Key值为:‘00000000’ (8个’0’)
放入ldb的该条记录Value值为:‘aaaaaaaaaaaaaaaa’ (16个’a’)
(Owed by: 春夜喜雨 http://blog.csdn.net/chunyexiyu)
leveldb的sstable-ldb解析相关推荐
- C++之String的find方法,查找一个字符串在另一个字符串的什么位置;leveldb字符串转数字解析办法...
由于leveldb基于key value,而且是根据字符串进行排序的.key 和value都是string类型的,对于我要处理的有许多数字,所以就要找一个C /C++解析文本的工具了. C 在这方面很 ...
- LevelDB的sstable解读
LevelDB分析 文章目录 1. 分析点 1.1 静态分析点 1.2 动态分析点 2. leveldb中的SSTable 2.1 引言 2.2 SSTable的layout 2.2 Data Blo ...
- Leveldb skiplist 实现及解析
skiplist 原理介绍 skiplist 由William Pugh 在论文Skip Lists: A Probabilistic Alternative to Balanced Trees 中提 ...
- Bigtable扩展——从 leveldb 的实现来理解 Bigtable 的 SSTable 数据结构
目录 一.Bigtable 中的 SSTable 二.LevelDB 对 SSTable 的具体实现 1.data block 数据结构 2.filter block 数据结构 3.meta inde ...
- 浅析 Bigtable 和 LevelDB 的实现
在 2006 年的 OSDI 上,Google 发布了名为 Bigtable: A Distributed Storage System for Structured Data 的论文,其中描述了一个 ...
- leveldb代码阅读笔记(一)
leveldb代码阅读笔记 above all leveldb是一个单机的键值存储的内存数据库,其内部使用了 LSM tree 作为底层存储结构,支持多版本数据控制,代码设计巧妙且简洁高效,十分值得作 ...
- LevelDb实现原理
原文地址:http://www.samecity.com/blog/Index.asp?SortID=12, 最近由于工作上的需求,需要用到leveldb,因此转载此文章用于以后的查询使用. Leve ...
- leveldb 详解
这是转载的一篇博客, 看到原博客, 甚是惊叹, 把leveldb分析理解的如此之深, 甚是佩服, 同时, 也表示感谢, 感谢分享! LevelDb日知录之一:LevelDb 101 说起LevelD ...
- LevelDB整体介绍
参考:http://www.cnblogs.com/haippy/archive/2011/12/04/2276064.html 1. leveldb简单介绍 说起LevelDb也许您不清楚,但是如果 ...
最新文章
- pythonisalpha函数计算公式_常用python实现.ipynb
- python画菱形的代码_python – 使用循环创建菱形图案
- 提高学生对计算机学科学习兴趣的研究的结题报告,《如何在体育教学中运用体育游戏》的研究结题报告...
- MyBatis foreach语句批量插入数据
- 2022-2028全球与中国无线电远程单元市场现状及未来发展趋势
- 和平精英怎么玩?智能找图、鼠标滚轮宏按键玩吃鸡还能匹配手机?
- mac 硬盘读写速度测试 软件,MAC硬盘速度测试技巧
- 超市扫码器应该怎么使用
- 说说用笔记本电脑的惨痛经历
- python zip压缩文件下载及解压
- 使用Python将word转换为pdf
- hiveserver2连接报错:“User: xxx is not allowed to impersonate yyy (state=08S01,code=0)”
- 误入 GitHub 游戏区,结果意外地收获颇丰
- LINUX(socket)网络编程部分头文件归纳解释
- Zero-shot Learning零样本学习 论文阅读(五)——DeViSE:A Deep Visual-Semantic Embedding Model
- android 异步编程,flutter异步编程-事件循环、Isolate、Stream(流)
- JAVA面试系列:你了解系统可用性吗?
- PrintSpool 服务经常自动停止!
- Altium Designer生产文件输出与文件归档
- 计算机毕设(附源码)JAVA-SSM驾校预约考试管理系统
热门文章
- 国家电网电力职称英语计算机网站,国网电力职称英语阅读理解.doc
- 信号完整性(SI)电源完整性(PI)学习笔记(二十六)S参数在信号完整性中的应用(一)
- Cisco交换机IOS备份还原
- ElementUI el-input 设置 type 类型为 number 时,如何去掉上下指示箭头
- nRF keil工程错误相关
- Riche million espérer interroger chasse.
- CSS压缩之:正则五步替换法
- Python+Selenium练习篇13-设置浏览器下载文件默认地址
- C# 大地测量高斯投影正反算公式计算程序
- ce修改面板属性_改属性【dnfce修改器吧】_百度贴吧