(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.
  1. 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解析相关推荐

  1. C++之String的find方法,查找一个字符串在另一个字符串的什么位置;leveldb字符串转数字解析办法...

    由于leveldb基于key value,而且是根据字符串进行排序的.key 和value都是string类型的,对于我要处理的有许多数字,所以就要找一个C /C++解析文本的工具了. C 在这方面很 ...

  2. LevelDB的sstable解读

    LevelDB分析 文章目录 1. 分析点 1.1 静态分析点 1.2 动态分析点 2. leveldb中的SSTable 2.1 引言 2.2 SSTable的layout 2.2 Data Blo ...

  3. Leveldb skiplist 实现及解析

    skiplist 原理介绍 skiplist 由William Pugh 在论文Skip Lists: A Probabilistic Alternative to Balanced Trees 中提 ...

  4. Bigtable扩展——从 leveldb 的实现来理解 Bigtable 的 SSTable 数据结构

    目录 一.Bigtable 中的 SSTable 二.LevelDB 对 SSTable 的具体实现 1.data block 数据结构 2.filter block 数据结构 3.meta inde ...

  5. 浅析 Bigtable 和 LevelDB 的实现

    在 2006 年的 OSDI 上,Google 发布了名为 Bigtable: A Distributed Storage System for Structured Data 的论文,其中描述了一个 ...

  6. leveldb代码阅读笔记(一)

    leveldb代码阅读笔记 above all leveldb是一个单机的键值存储的内存数据库,其内部使用了 LSM tree 作为底层存储结构,支持多版本数据控制,代码设计巧妙且简洁高效,十分值得作 ...

  7. LevelDb实现原理

    原文地址:http://www.samecity.com/blog/Index.asp?SortID=12, 最近由于工作上的需求,需要用到leveldb,因此转载此文章用于以后的查询使用. Leve ...

  8. leveldb 详解

    这是转载的一篇博客, 看到原博客,  甚是惊叹, 把leveldb分析理解的如此之深, 甚是佩服, 同时, 也表示感谢, 感谢分享! LevelDb日知录之一:LevelDb 101 说起LevelD ...

  9. LevelDB整体介绍

    参考:http://www.cnblogs.com/haippy/archive/2011/12/04/2276064.html 1. leveldb简单介绍 说起LevelDb也许您不清楚,但是如果 ...

最新文章

  1. pythonisalpha函数计算公式_常用python实现.ipynb
  2. python画菱形的代码_python – 使用循环创建菱形图案
  3. 提高学生对计算机学科学习兴趣的研究的结题报告,《如何在体育教学中运用体育游戏》的研究结题报告...
  4. MyBatis foreach语句批量插入数据
  5. 2022-2028全球与中国无线电远程单元市场现状及未来发展趋势
  6. 和平精英怎么玩?智能找图、鼠标滚轮宏按键玩吃鸡还能匹配手机?
  7. mac 硬盘读写速度测试 软件,MAC硬盘速度测试技巧
  8. 超市扫码器应该怎么使用
  9. 说说用笔记本电脑的惨痛经历
  10. python zip压缩文件下载及解压
  11. 使用Python将word转换为pdf
  12. hiveserver2连接报错:“User: xxx is not allowed to impersonate yyy (state=08S01,code=0)”
  13. 误入 GitHub 游戏区,结果意外地收获颇丰
  14. LINUX(socket)网络编程部分头文件归纳解释
  15. Zero-shot Learning零样本学习 论文阅读(五)——DeViSE:A Deep Visual-Semantic Embedding Model
  16. android 异步编程,flutter异步编程-事件循环、Isolate、Stream(流)
  17. JAVA面试系列:你了解系统可用性吗?
  18. PrintSpool 服务经常自动停止!
  19. Altium Designer生产文件输出与文件归档
  20. 计算机毕设(附源码)JAVA-SSM驾校预约考试管理系统

热门文章

  1. 国家电网电力职称英语计算机网站,国网电力职称英语阅读理解.doc
  2. 信号完整性(SI)电源完整性(PI)学习笔记(二十六)S参数在信号完整性中的应用(一)
  3. Cisco交换机IOS备份还原
  4. ElementUI el-input 设置 type 类型为 number 时,如何去掉上下指示箭头
  5. nRF keil工程错误相关
  6. Riche million espérer interroger chasse.
  7. CSS压缩之:正则五步替换法
  8. Python+Selenium练习篇13-设置浏览器下载文件默认地址
  9. C# 大地测量高斯投影正反算公式计算程序
  10. ce修改面板属性_改属性【dnfce修改器吧】_百度贴吧