leveldb源码分析--Comparator
既然leveldb是一个按Key序组织的LSM-Tree实现,那么对于Key的比较就是非常之重要了,这个Key的比较在leveldb中是Comparator的形式出现的。我们首先来看看Comparator的基本方法有哪些
// 实际的比较函数
virtual int Compare(const Slice& a, const Slice& b) const = ; // 名称,主要是为了防止建立和读取时使用了不同的Comparator
virtual const char* Name() const = ; //找出 [start, limit)之间的一个短的串,主要作用是降低一些存储空间
virtual void FindShortestSeparator(
std::string* start,
const Slice& limit) const = ; //作用类似,但无上端限制
virtual void FindShortSuccessor(std::string* key) const = ;
在leveldb中已经实现的类有两个,一个是内置的BytewiseComparatorImpl,另一个是InternalKeyComparator。我们首先来分析BytewiseComparatorImpl的实现,实现十分简单,我们这里只对实现的功能用注释的方式进行说明
// Bytewise直接调用Slice的Compare,按memcmp的方式进行比较,然后再比较长短
int Compare(const Slice& a, const Slice& b)
//对start和limit的公共部分外的start中的可以uint8方式+1的字节+1,清除该位之后的数据
void FindShortestSeparator(std::string* start, const Slice& limit)//直接对key中第一个可以uint8方式+1的字节+1,清除该位后面的数据
void FindShortSuccessor(std::string* key)
我们分析InternalKeyComparator的内部实现,看其成员变量其包含了一个Comparator类型的user_comparator_,其比较都用到了这个成员变量的方法,这个类的实现是在使用这些方法的过程中加入了一些解码的过程。根据其解码过程和名字我们可以看出这个比较器是用来比较传入为InternalKey对象,我们知道其组成为
user_key (string) | sequence ( byte) | value_type ( byte)
对于InternalKeyComparator的三个函数的具体实现说明为
// 传入的值解码得到user_key后对user_key进行比较
int Compare(const Slice& a, const Slice& b)
//解码后对user_key FindShortestSeparator,然后再最后加入kMaxSequenceNumber|kValueTypeForSeek
void FindShortestSeparator(std::string* start, const Slice& limit)//将key的第一个可以+1的字节+1,然后加上kMaxSequenceNumber|kValueTypeForSeek
void FindShortSuccessor(std::string* key)
我们再来看看MemTable关于Table 的定义
typedef SkipList<const char*, KeyComparator> Table;
Table table_; 而 KeyComparator的定义为:
struct KeyComparator {
const InternalKeyComparator comparator;
explicit KeyComparator(const InternalKeyComparator& c) : comparator(c) { }
int operator()(const char* a, const char* b) const;
};
由此可知KeyComparator是一个引用了InternalKeyComparator作为成员变量的结构体,而InternalKeyComparator又引用了一个 Comparator类型的user_comparator_。理清了了这些所谓的Comparator的引用层次关系以后,我们来看看leveldb中定义SkipList是使用的哪个Comparator。首先看MemTable的构造函数
MemTable::MemTable(const InternalKeyComparator& cmp)
: comparator_(cmp),
refs_(),
table_(comparator_, &arena_) {
}
可以看到构造函数接收一个InternalKeyComparator类型的参数,然后构建内部的KeyComparator,然后在将其传递给SkipList 的table_,而通过查找我们看到其构造是在DBImpl的构造函数中被调用的,看代码
DBImpl::DBImpl(const Options& raw_options, const std::string& dbname)
: env_(raw_options.env),
internal_comparator_(raw_options.comparator),
......
mem_(new MemTable(
internal_comparator
_)),
再继续往下找到有如下代码
Status DB::Open(const Options& options, const std::string& dbname,
DB** dbptr) {
DBImpl* impl = new DBImpl(options, dbname);
......
}
所以我们可以得出结论是最终的SkipList中使用的Comparator就是在Open数据库的时候传入的参数Option中的成员变量comparator,所以我们在实现自己的Comparator的时候只有仿照BytewiseComparatorImpl实现一个,然后通过option的方式传递给leveldb即可。
最后我们整理一下思路:
1. SkipList中使用的KeyComparator仅仅是对InternalKeyComparator的一个包含式的封装;
2. 而InternalKeyComparator是对key的简单编解码后使用option中传入的Comparator,默认为BytewiseComparatorImpl
InternalKeyComparator中的编解码是user_key和InternalKey之间的转换,所以最终的顺序(大小)的比较其实都是user_key(Put,Get,Delete传入的Key值)根据option中的Comparator(默认为BytewiseComparatorImpl)进行compare得出顺序。
理清这个顺序以后对leveldb中的各个Comparator就比较容易理解了。
leveldb源码分析--Comparator的更多相关文章
- leveldb源码分析--Key结构
[注]本文参考了sparkliang的专栏的Leveldb源码分析--3并进行了一定的重组和排版 经过上一篇文章的分析我们队leveldb的插入流程有了一定的认识,而该文设计最多的又是Batch的概念 ...
- leveldb源码分析--SSTable之block
在SSTable中主要存储数据的地方是data block,block_builder就是这个专门进行block的组织的地方,我们来详细看看其中的内容,其主要有Add,Finish和CurrentSi ...
- leveldb源码分析--WriteBatch
从[leveldb源码分析--插入删除流程]和WriteBatch其名我们就很轻易的知道,这个是leveldb内部的一个批量写的结构,在leveldb为了提高插入和删除的效率,在其插入过程中都采用了批 ...
- Leveldb源码分析--1
coming from http://blog.csdn.net/sparkliang/article/details/8567602 [前言:看了一点oceanbase,没有意志力继续坚持下去了,暂 ...
- leveldb源码分析--日志
我们知道在一个数据库系统中为了保证数据的可靠性,我们都会记录对系统的操作日志.日志的功能就是用来在系统down掉的时候对数据进行恢复,所以日志系统对一个要求可靠性的存储系统是极其重要的.接下来我们分析 ...
- 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内核也有个内存池.内存池的存在主要就是减 ...
随机推荐
- 一口一口吃掉Volley(三)
欢迎访问我的个人博客转发请注明出处:http://www.wensibo.top/2017/02/17/一口一口吃掉Volley(三)/ 学习了一口一口吃掉Volley(二)之后,你应该已经学会了如何 ...
- springboot 多模块 -- 将 dao(mybatis) 拆分出去
前言: 以前我们在建项目的时候, 要么将所有的package建在一个项目里面, 在处理引用的时候, 真的很方便. 不用担心, 有些东西配置不到或者读取不到. 或者, 将package独立出去, 到一个 ...
- 初入Java后端之Servlet
初入Java后端之Servlet 后端 Servlet 什么是Servlet? Servlet实际上是一个按照Servlet规范写的Java类.是运行在Web服务端的Java应用程序.与Java程序 ...
- C# Owin初探 概念理解(一)
本文是阅读网上大牛的文章总结而成. 目录 1.Owin定义 2.为什么要用Owin 3.作用 4.总结 1.Owin定义 Owin是Open Web Interface For .NET.也就是.Ne ...
- 基于asp.net mvc的近乎产品开发培训课程(第四讲)
演示产品源码下载地址:http://www.jinhusns.com/Products/Download 演示产品源码下载地址:http://www.jinhusns.com/Products/Do ...
- 反射实现Model修改前后的内容对比
在开发过程中,我们会遇到这样一个问题,编辑了一个对象之后,我们想要把这个对象修改了哪些内容保存下来,以便将来查看和追责. 首先我们要创建一个User类 public class User { priv ...
- CSS学习笔记01 CSS简介
1.CSS定义 CSS 指层叠样式表 (Cascading Style Sheets),是一种样式表语言,用来描述 HTML 或 XML(包括如 SVG.XHTML 之类的 XML 分支语言)文档的呈 ...
- 二叉搜索树(hdu3791)
二叉搜索树 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Subm ...
- PHP中按值传递和引用传递的区别
有次跟朋友讨论对象传值的方式时提到引用传值时,在大脑中搜索五秒钟,果断确定在这两个项目当中并没有用到.今天去问了一下度娘,顺便做了个小测试: 按值传递: 引用传递: 按值传递中原来参数的值在调用其他函 ...
- Angular 实现Bootstrap ScrollSpy控件
Bootstap是基于JQuery开发,Angular中不支持Bootstrap相关事件逻辑.本文基于Typecript开发了一个Angular可用的ScrollSpy控件.Scrollspy控件主要 ...