造轮子之leveldb
文章平均质量分 70
uestc-leon
我想做一个强者
展开
-
leveldb(二):Arena
Arena是Leveldb的简单的内存池,它所作的工作十分简单,申请内存时,将申请到的内存块放入std::vector blocks_中,在Arena的生命周期结束后,统一释放掉所有申请到的内存,内部结构如图所示。 class Arena { public: Arena(); ~Arena();//析构函数统一释放所有申请的内存 char* Allocate(size_t bytes)原创 2017-06-28 15:49:18 · 332 阅读 · 0 评论 -
leveldb:write(如何处理并发写操作)
Put与Delete操作Status DB::Put(const WriteOptions& opt, const Slice& key, const Slice& value) { WriteBatch batch; batch.Put(key, value); return Write(opt, &batch);}Status DB::Delete(const WriteOptio原创 2017-09-29 14:07:33 · 5875 阅读 · 0 评论 -
leveldb(六):key的不同种类型
有5个key的概念,可能会让人混淆,下面就来一个一个的分析。 User_key;最简单的key了,就是用户传入的数据 Slice user_key;ParsedInternalKeyenum ValueType { kTypeDeletion = 0x0, kTypeValue = 0x1};//我们后面会讲到,我们对key进行delete操作时其实也是插入一条记录,只不过Value原创 2017-07-30 20:19:45 · 3955 阅读 · 0 评论 -
leveldb(八):log::Writer写日志
5 操作Log 1分析完KV在内存中的存储,接下来就是操作日志。所有的写操作都必须先成功的append到操作日志中,然后再更新内存memtable。这样做有两个有点:1可以将随机的写IO变成append,极大的提高写磁盘速度;2防止在节点down机导致内存数据丢失,造成数据丢失,这对系统来说是个灾难。在各种高效的存储系统中,这已经是口水技术了。5.1 格式在源码下的转载 2017-07-31 11:32:10 · 1130 阅读 · 0 评论 -
leveldb:DBIter
DBIter的作用Leveldb数据库的MemTable和sstable文件的存储格式都是InternalKey(userkey, seq, type) => uservalue。 DBIter把同一个userkey在DB中的多条记录合并为一条,综合考虑了userkey的序号、删除标记、和写覆盖等等因素。DBIter只会把userkey最新(seq最大的就是最新的,相同userkey的老记录(se原创 2017-12-02 17:58:53 · 841 阅读 · 1 评论 -
leveldb:数据库recover机制
DBImpl::Recover把数据库恢复到上次退出的状态,Recover的基本功能是:首先是处理创建flag,比如存在就返回失败等等;然后是尝试从已存在的sstable文件恢复db;最后如果发现有大于原信息记录的log编号的log文件,则需要回放log,更新db数据。回放期间db可能会dump新的level 0文件,因此需要把db元信息的变动记录到edit中返回。Status DBImpl::Re原创 2017-09-19 14:12:33 · 3340 阅读 · 1 评论 -
leveldb:DB::Open创建一个新数据库或者打开一个已存在的数据库
leveldb文件类型 上面的log文件,sst文件,临时文件,清单文件末尾都带着序列号,序号是单调递增的(随着next_file_number从1开始递增),以保证不会和之前的文件名重复。另外,注意区分db log与info log:前者是为了防止保障数据安全而实现的二进制Log,后者是打印引擎中间运行状态及警告等信息的文本log。 随着更新与Compaction的进行,LevelDB会不断生原创 2017-11-09 10:51:10 · 5046 阅读 · 0 评论 -
用fallocate进行"文件预留"或"文件打洞"
什么是空洞文件?“在UNIX文件操作中,文件位移量可以大于文件的当前长度,在这种情况下,对该文件的下一次写将延长该文件,并在文件中构成一个空洞,这一点是允许的。位于文件中但没有写过的字节都被设为 0。” 如果 offset 比文件的当前长度更大,下一个写操作就会把文件“撑大(extend)”。这就是所谓的在文件里创造“空洞(hole)”。没有被实际写入文件的所有字节由重复的 0 表示。空洞是否占用硬原创 2017-12-16 23:04:09 · 19735 阅读 · 0 评论 -
leveldb:合并之DoCompactionWork(多文件间的合并)
再来分析DoCompactionWork前,我们先来熟悉几个与DoCompactionWork相关的数据结构Compactionclass Compaction { public: ~Compaction(); // 返回将要合并的层数,我们将level_与level_+1中冲突的文件合并到level_+1层 int level() const { return level_; } /原创 2017-09-22 16:55:32 · 1911 阅读 · 0 评论 -
leveldb和rocksdb在大value场景下的一些问题
Table of Contents1 问题1.1 compaction不可控.1.2 写放大1.3 其它问题2 小结Leveldb 2011年7月开源, 到现在有3年了, 原理上已经有很多文章介绍了, 我们就不多说.其中最好的是淘宝那岩写的 leveldb 实现解析 和 TokuMX作者写的那个300页ppt: A C转载 2017-11-05 16:56:54 · 6357 阅读 · 0 评论 -
leveldb:VersionEdit与MANIFEST文件
VersionEdit和MANIFEST文件到底是什么关系?VersionEdit会保存在MANIFEST文件中。VersionEdit就相当于MANIFEST文件中的一条记录。 VersionEdit是version对象的变更记录,用于写入MANIFEST文件。这样通过原始的version加上一系列的versionedit的记录,就可以恢复到最新状态。VersionEdit分析下面来看Versi原创 2017-09-14 11:32:26 · 1710 阅读 · 0 评论 -
leveldb:VersionSet
VersionSet 是version组成一个双向循环链表。class VersionSet{//. . . Env* const env_;// 操作系统封装 const std::string dbname_; const Options* const options_; TableCache* const table_cache_; const InternalKeyC转载 2017-09-15 14:26:40 · 1654 阅读 · 0 评论 -
leveldb:version分析
class Version { public: //生成iterator用于遍历 void AddIterators(const ReadOptions&, std::vector<Iterator*>* iters); //根据key来查询,GetStats记录了第一个读取的文件 struct GetStats { FileMetaData* seek_file;转载 2017-09-14 19:13:26 · 513 阅读 · 0 评论 -
leveldb(一):AtomicPointer
AtomicPointer 简介AtomicPointer 是 leveldb 提供的一个原子指针操作类,使用了基于内存屏障的同步访问机制,这比用锁和信号量的效率要高。源文件位置:leveldb/port/atomic_pointer.h 它的实现主要分为两种:(一)利用std::atomic实现AtomicPointer std::atomic对int, char, bool等数据结构进行原子原创 2017-06-28 14:58:26 · 1414 阅读 · 1 评论 -
leveldb(三):Slice
levelDB中Slice非常简单的数据结构,它包括length和一个指向外部字节数组的指针。为什么使用Slice,而不直接使用std::string呢?1、相比返回string,返回Slice的开销会小的多(没有拷贝(数据),Slice中没有实际数据,只有指向数据的指针,开销低,因为拷贝也只是拷贝了指针而已)。 2、leveldb允许key和value包含’\0’,不能返回以null结尾的c原创 2017-07-14 19:03:36 · 709 阅读 · 0 评论 -
leveldb(四):Cache
cache是怎么组织的cache中的每个元素既在一个双向的lru链表中,同时又在一个hash表中。 lru链表的作用是:当cache超过容量时淘汰掉最旧的元素, hash表的作用是:对cache中的元素进行快速定位。cache中的元素下面我们来看看cache中的元素是长啥样的,leveldb用LRUHandle结构体代表cache中的元素。struct LRUHandle { //node原创 2017-07-10 21:22:03 · 417 阅读 · 0 评论 -
leveldb(五):SkipList跳表
跳表原理的简单介绍跳表是平衡树的一种替代的数据结构,但是和红黑树不相同的是,跳表对于树的平衡的实现是基于一种随机化的算法的,这样也就是说跳表的插入和删除的工作是比较简单的。下面来研究一下跳表的核心思想:先从链表开始,如果是一个简单的链表,那么我们知道在链表中查找一个元素I的话,需要将整个链表遍历一次。 如果是说链表是排序的,并且节点中还存储了指向前面第二个节点的指针的话,那么在查找一个节点时,仅原创 2017-07-30 16:44:23 · 1570 阅读 · 0 评论 -
leveldb(七):Memtable
4 Memtable先写点最精妙的部分:我们在插入一条k/v记录时是把k和v整合在一起当成一个新的key插入到跳表里,因为我们的跳表里只有key没有value。查询(get)我们传入的仅仅是k,但跳表里的comparator是我们自己指定的,所以comparator会比较跳表中node里key的k部分和我们传入的k作比较,如果符合就把key的v部分返回。4.6 Comparator转载 2017-07-30 22:32:15 · 319 阅读 · 0 评论 -
leveldb(九):log::Reader读日志
5 操作Log 2 5.3 读日志日志读取显然比写入要复杂,要检查checksum,检查是否有损坏等等,处理各种错误。5.3.1 类层次先来看看读取涉及到的类图,如图5.3-1。Reader主要用到了两个接口,一个是汇报错误的Reporter,另一个是log文件读取类SequentialFile。> Reporter的接口只有一个:void Co转载 2017-07-31 11:43:19 · 1244 阅读 · 1 评论 -
leveldb(十):SSTable之1sstable文件的组成结构
个人总结:1.sstable是由很多种不同类型的block组成的,每种block的功能各自不同,详见下,但他们的存储格式都是相同的,都利用了共享前缀压缩以及二分查找的技巧。2.Leveldb对block的管理是读写分离的,读取后的遍历查询操作由Block类实现,block的构建则由BlockBuilder类实现。对于Block,它其实是把整个block的内容都读到内存data_上,而B转载 2017-07-31 14:49:34 · 590 阅读 · 0 评论 -
leveldb(十一):SSTable之2写sstable文件
个人总结:1.由上一篇我们知道了一个sstable文件是由很多个不同的block组成的,其中最重要的两个是Data Block和Index Block。我们知道除了第0层,其他层的sstable都是按key增长的顺序存储kv对的。Data Block就是存储这些kv对的block。每个Data Block管一段key的范围。Index Block就是负责记录每段key是在哪个Data Bl转载 2017-08-02 11:12:40 · 598 阅读 · 1 评论 -
leveldb:TableCache以及BlockCache
概述前面分析了leveldb中cache机制的实现,下面来分析下leveldb基于cache机制实现的两个不同功能的cache,分别是table cache和block cache。table cache缓存的是sstable的索引数据,类似于文件系统中对inode的缓存;block cache是缓存的block数据,block是sstable文件内组织数据的单位,也是从持久化存储中读取和写入原创 2017-10-26 20:45:11 · 1662 阅读 · 0 评论