标签归档:源码分析

leveldb注释8–snapshot机制

snapshot,也就是快照机制的作用,就是使得读操作不受写操作影响。其巧妙的使用了SequenceNumber来实现这一机制。 上一节中,我们知道,SequenceNumber使得对写入的任何key在内部存储时都会附加一个递增的SequenceNumber。而在leveldb内部,一次snapshot也对应一个全局唯一的SequenceNumber。因此,在调用GetSnapshot获取snapshot时,leveldb所做的仅仅是生成一个SequenceNumber。db内部使用双向循环链表保存先后生成的snapshot。

发表在 leveldb | 标签为 , , , | 4 条评论

leveldb注释7–key与value

作为一个kv的系统,key的存储至关重要。在leveldb中,主要涉及到如下几个key,user_key、InternalKey与LookupKey(memtable_key)。 其关系构成如下图。user_key就是用户输入的key,而InternalKey在user_key的基础上封装了sequence_num+type。sequence_num是一个全局递增的序列号,每一次Put操作都会递增。这样,不同时间的写入操作会得到不一样的sequence_num。前面章节中提到的sstable单条record中的key,其内部其实就是一个InternalKey。sequence_num主要跟snapshot机制与version机制相关,对压缩会产生一定影响。这些我们在后续章节分析。根据type字段,可以获知本次写入操作是写还是删除(也就是说删除是一种特殊的写)。而LookupKey/memtable_key用于在memtable中,多了一个长度字段。代码主要在dbformat.cc/.h中。

发表在 leveldb | 标签为 , , , | 留下评论

leveldb注释6–log文件

在leveldb中,除了sstable文件格式,还有log文件格式。该文件格式用于存储写操作的日志与manifest文件(不同的文件名)。前者用于异常回滚。后者用于记录sstable文件的元数据。整体架构中提到过,leveldb在将记录写入内存中的memtable之前,会先写入log文件,memtable会延后持久化。在这个过程中进程可能down掉。有了log写操作文件后,即使系统发生故障,levelDB也可以根据log写操作日志文件恢复内存的memtable内容,不会造成丢失数据。而manifest文件用于记录所有的sstable文件的元数据,比如sstable文件的编号,key范围。

发表在 leveldb | 标签为 , , , | 留下评论

leveldb注释5–sstable文件

本节主要介绍sstable文件的格式及单个sstable文件的get/put。sstable文件全称是sorted string table,是一个有序且带索引的文件。 从前面的分析可知,level 0级的sstable文件是由内存中的immunable memtable经过minor compact形成的(也就是直接dump),而level>0级的文件是由level-1级别的文件经过major compact形成的。关于compact过程,我们在后续章节分析。这里着重于分析单个sstable文件的相关接口,代码在table/目录。

发表在 leveldb | 标签为 , , , | 留下评论

leveldb注释4–平台相关

0 编译 leveldb没有使用autoconf/automake来生成Makefile,而是自己编写了Makefile以及平台检测脚本。Makefile中会先调用检测脚本build_detect_platform,并将设置的环境变量保存在build_config.mk文件里。随后Makefile会include build_config.mk文件以进行编译,相关Makefile代码如下,其中的PLATFORM_CCFLAGS等参数将在build_detect_platform中设置并输出给build_config.mk文件:

发表在 leveldb | 标签为 , , , , | 留下评论

leveldb注释3–基础类

这一节主要分析下util目录下的代码。这部分代码相对独立,功能明确,很容易看明白。可先尝试理解这部分代码,以为进一步理解leveldb代码打下基础。 1 内存管理(arena.cc/.h)

发表在 leveldb | 标签为 , , , , , , , , , , | 留下评论

leveldb注释1–整体介绍

概括的说,leveldb是一个kv型的存储库。主要特点如下: > 单机嵌入式接口 > 持久化存储 > KV系统,提供读写删除操作(kv都是字节序列) > 支持快照功能,使得读操作不受写操作影响 > 磁盘上的数据是有序的,且分级存储,同时在文件保存相应的索引以加速读操作 > 删除是一种特殊类型的写操作 > 提供压缩操作以减少存储空间 > 写入,延迟写入,通过log保证数据不丢失 整体架构如下图所示:

发表在 leveldb | 标签为 , , | 一条评论

leveldb注释0–start

因为工作需要,曾对leveldb进行过测试与实际使用,而对leveldb的源代码进行学习,则纯粹是出于一个码农对美好世界进行探究的好奇。接下来将尽可能从源代码上给出leveldb代码的详尽注释,这里先列出自己在阅读前后的主要参考。

发表在 leveldb | 标签为 , , | 留下评论

redis源代码分析2–动态字符串

redis的字符串号称是二进制安全的,其内部实现其实就是个head+ char*。 typedef char *sds; struct sdshdr { long len; long free; char buf[]; }; len 表示buf字符数组实际使用的空间大小,free表示buf剩余空间大小,buf所分配的空间大小等于len+free。尽管一开始buf的大小等于 len(当然可以大于),但随着字符串连接、拷贝(C中的字符串函数),buf分配的空间很可能会比len大,此时redis并不会释放多出的内存。 redis源代码分析2–动态字符串

发表在 redis | 标签为 , , | 2 条评论

redis源代码分析1–链表

先简单介绍下redis中用到的链表,是在文件adlist.c和adlist.h中实现的。 实现中主要用到listNode、list、listIter三个结构,listNode代表链表中的每个节点,list指向整个链表,listIter是为了迭代访问整个list,内部其实就是个listNode指针。 typedef struct listNode { struct listNode *prev; struct listNode *next; void *value; } listNode; typedef struct listIter { listNode *next; int direction; } listIter; typedef struct list { listNode *head; listNode *tail; void *(*dup)(void *ptr); void(*free)(void *ptr); int(*match)(void … 继续阅读

发表在 redis | 标签为 , , | 7 条评论