前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >SSTable 介绍

SSTable 介绍

作者头像
狼啸风云
修改2022-09-03 19:46:10
2.4K0
修改2022-09-03 19:46:10
举报

如果说Protocol Buffers是Google内部表示独立数据记录的单元,那么排序的字符串表--Sorted String Table(SSTable)--是存储,处理和交换数据集的最流行的输出之一。正如名字本身所包含的意思一样,SSTable是一个简单的抽象,用来高效地存储大量的键-值对数据,同时做了优化来实现顺序读/写操作的高吞吐量。

SSTable的适用场景:

SSTable的产生背景:

假设我们需要处理输入量级在G或者T字节级别的一系列任务。而且我们需要执行很多步骤,这些步骤是不同的程序执行的--换句话说,假设我们在运行一系列的Map-Reduce任务。鉴于输入的数据量级很大,所以读取和写入数据就能够占运行时间的大头。因此,就不考虑随机读取和写入的情况了,相反我们流式处理输入数据,一旦处理完成,同样利用流式操作把结果数据写回到磁盘上。这样,我们可以摊薄磁盘I/O操作的成本

所以SSTable是一个简单,但是非常有用的用来交换大量的、排好序的数据片段的数据结构。它的使用场景是:

  • 需要高效地存储大量的键-值对数据
  • 数据是顺序写入
  • 要求高效地顺序读写
  • 没有随机读取或者对随机读取性能要求不高

SSTable简介:

Google Bigtable论文中对SSTable的介绍:

SSTable提供一个可持久化[persistent],有序的、不可变的从键到值的映射关系,其中键和值都是任意字节长度的字符串。SSTable提供了以下操作:按照某个键来查询关联值,可以指定键的范围,来遍历其中所有的键值对。每个SSTable内部由一系列块(block)组成(通常每块大小为64KB,是可配置的)。使用存储在SSTable结尾的块索引(block index)来定位块;当SSTable打开时,索引会被加载到内存里。一次磁盘寻道(disk seek)就可以完成查询(lookup)操作:首先通过二分查找在存储在内存的索引中找到对应的块,然后从磁盘上读取这块内容。SSTable也可以完整地映射到内存里,这样在执行查询和扫描(scan)的时候就不用操作磁盘了.

所以可以简单的总结: SSTable是一个键是有序的,存储字符串形式键值对的文件。

SSTable的设计:

sstable
sstable

"Sorted String Table"就如名字所言,它是一个内部包含了任意长度、排好序的键值对<key,value>集合的文件。其结构如上图所示,SSTable文件由两部分数据组成:索引和键值对数据。所有的key和value都是紧凑地存放在一起的,如果要读取某个键对应的值,需要通过索引中的key:offset来定位。

从上图可以看到,因为SSTable文件中所有的键值对<key,value>是存放到一起的,所以SSTable在序列化成文件之后,是不可变的,因为此时的SSTable,就类似于一个数组一样,如果插入或者删除,需要移动一大片数据,开销比较大。

顺序读取整个文件,就拿到了一个排好序的索引。如果文件很大,还可以为了加速访问而追加或者单独建立一个独立的key:offset的索引。

leveldb中,SSTable的实现

leveldb/目录是存放对外开放的API头文件的目录,对作用域等做了严格的限制,为了避免引入多余的依赖关系,比较多的使用了类和结构体的前置声明[forward declaration]。 SSTable对应的实现是Table类,头文件是:include/leveldb/table.h。通过Table类开头的注释可以看到Table是不可变的,可持久化的。SSTable由于是不可改变的,只读的,所以是线程安全的,不需要外界的同步操作。

Table对外接口:

Table类只提供了简单的3个操作:

  1. 通过文件来反序列化,读取SSTable的数据:static Status Open(const Options& options, RandomAccessFile* file, uint64_t file_size, Table** table);
  2. 获得用来访问SSTable数据的迭代器:Iterator* NewIterator(const ReadOptions&) const SSTable的数据读取都是通过迭代器进行的,迭代器也只允许读取操作,没有提供写入操作。
  3. 预估key[可能还没有写入到SSTable中]对应的数据存储到SSTable文件的偏移:uin64_t ApproximateOffsetOf(const Slice& key) const leveldb对外提供了GetApproximateSizes()--通过指定key的范围来获取存储这些数据的文件大致大小的功能,所以需要底层的这些数据结构也来提供对应的功能。同时这类函数也能提高leveldb系统的可测性,通过文件的大小就可以判断写入数据是否正常。

可以看到SSTable的拷贝构造函数Table(const Table)和赋值函数void operator=(const Table&)都是私有的,这样就是禁止SSTable对象的拷贝了。Table类的使用方,只能通过Open接口来反序列化SSTable对象。

Table需要知道的类和结构体

通过table.h头文件可以看到它需要打交道的类或者结构体主要有:

  • class Block: 上文提到每个SSTable文件由一系列可配置大小的块(block)组成。Block就是对block块数据的封装,对外提供size()和迭代器Iterator接口。
  • class BlockHandle 定义在table/format.h中,代表了存储数据的文件的范围:偏移offset+大小size
  • class Footer: 定义在table/format.h中,封装了在每个SSTable文件尾部存储的固定大小的元数据信息(metadata),包含了两部分数据:metaindex和index数据。index数据就是上文中提到的SSTable的索引数据,而metaindex存储的是过滤器(例如布隆过滤器)的信息。利用过滤器,可以显著地减少磁盘访问。
  • class RandomAccessFile: SSTable关联的文件,是可以随机读取的文件:可以指定从哪里开始读,读取多少字节,方便SSTable按照需要去读取block的数据
  • struct ReadOptions, Struct Options 把一堆选项相关的参数定义到结构体里,方便传递参数,也方便理解,否则看到的就是一堆参数了。
  • class TableCache 一个SSTable的缓存(cache),每次需要对某个SSTable文件要做读取操作时,去对应的TableCache里面进行操作[如果没有命中缓存,会加载这个SSTable数据并更新缓存]。TableCache里面包含了SSTable的全部内容:索引+数据
  • struct Table::Rep 定义在table.cc中[是Table类内部使用的结构体],存储了SSTable相关的一些元数据,例如当前SSTable实例对应的文件句柄[file]、在Table缓存中的句柄[cache_id]、过滤器的读取对象[filter]、过滤器的数据[filter_data]、元索引[metaindex_handle]和索引[index]数据。有了这些数据,就可以唯一地代表一个SSTable的数据了。

单独说一下迭代器Iterator,此接口类提供了丰富的数据访问操作,所有对SSTable和SSTable中block的读取操作都用迭代器来进行。迭代器定义在include/leveldb/iterator.h中,这里也只是定义了一个迭代器的接口类,规定了对外的统一接口函数,这些接口函数都是纯虚函数,需要子类去实现。在leveldb中可以看到很多这样的例子,这就是面向接口编程的思想。通过迭代器类Iterator的定义看到,table类对外的数据访问只能通过迭代器类Iterator来进行,而且迭代器只提供读取操作,key()和value()函数都是const类型,不允许修改Iterator类内部的数据。迭代器还提供了RegisterCleanup函数,可以用挂接多个CleanupFunction类型的回调函数并自定义两个参数。CleanupFunction是用来在迭代器销毁时,做自定义的清理工作。

从format.h中还可以看到Table定义了Table内部使用的类和结构体:

  • struct BlockContents 封装了SSTable中每一个block的数据信息,包含实际存储的数据(Slice data), 是否可以缓存(bool cacheable), 是否需要调用方释放存储数据的内存这三类信息。

SSTable的特点

代码语言:javascript
复制
* 存储的是<键,值>格式的字节数据
* 字节数据的长度随意,没有限制
* 键可以重复, 键值对不需要对齐
* 随机读取操作非常高效

SSTable的限制

代码语言:javascript
复制
*   一旦SSTable写入硬盘后,就是不可变的,因为插入或者删除需要对SSTable文件进行大量的I/O操作
* 不适合随机读取和写入,因为效率很低,原因同上一条

关于SSTable的设计,还有一些东西没有介绍,例如在磁盘上存储的具体格式,如何序列化等,留待下一篇介绍。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019-12-04 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • SSTable的适用场景:
  • SSTable简介:
  • SSTable的设计:
  • leveldb中,SSTable的实现
  • SSTable的特点
  • SSTable的限制
相关产品与服务
对象存储
对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档