MySQL · RocksDB · 数据的读取(一)

概述

简而言之,在RocksDB中的读取需要处理的最核心的一个问题就是如何读取最新的数据,这是由于RocksDB是基于LSM,因此在RocksDB中,对于数据的delete以及update,它并不会立即去执行对应的动作,而只是插入一条新的数据,而数据的最终更新(last-write-win)以及删除是在compact的时候来做的.

阅读全文

MySQL · RocksDB · Level Compact 分析

综述

在RocksDB中,将MemTable刷新到磁盘之后,将会有很多sstable,而这些sstable则是可能包含了相同的key的不同时间的值,这样子就会导致两个问题:

阅读全文

MySQL · RocksDB · Memtable flush分析

概述

首先我们知道在RocksDB中,最终数据的持久化都是保存在SST中,而SST则是由Memtable刷新到磁盘生成的,因此这次我们就主要来分析在RocksDB中何时以及如何来Flush内存数据(memtable)到SST.

阅读全文

MySQL · RocksDB · MemTable的写入

简介

在之前的文章中我们知道RocksDB每一次写入,都是先写WAL,然后写Memtable,这次我们就来分析下MemTable的实现.

在RocksDB中,每个ColumnFamily都有自己的Memtable,互不影响.而在RocksDB中Memtable有多种实现(SkipList/HashSkipList/HashLinkList/Vector),具体的区别可以看这里,我们这次主要来分析默认的实现skiplist(只有skiplist是可以并发插入的).

阅读全文

MySQL · RocksDB · 写入逻辑的实现

简介

在RocksDB中,每次写入它都会先写WAL,然后再写入MemTable,这次我们就来分析这两个逻辑具体是如何实现的.
首先需要明确的是在RocksDB中,WAL的写入是单线程顺序串行写入的,而MemTable则是可以并发多线程写入的。

阅读全文

MySQL · RocksDB · Column Family介绍

概述

在RocksDB 3.0中加入了Column Family特性,加入这个特性之后,每一个KV对都会关联一个Column Family,其中默认的Column Family是 “default”.
Column Family主要是提供给RocksDB一个逻辑的分区.从实现上来看不同的Column Family共享WAL,而都有自己的Memtable和SST.这就意味着我们可以很
快速已经方便的设置不同的属性给不同的Column Family以及快速删除对应的Column Family.

阅读全文

MySQL · RocksDB · MANIFEST文件介绍

概述

在RocksDB中MANIFEST保存了存储引擎的内部的一些状态元数据,简单来说当系统异常重启,或者程序异常被退出之后,RocksDB需要有一种机制能够恢复到一个一致性的状态,
而这个一致性的状态就是靠MANIFEST来保证的.

阅读全文

MySQL · RocksDB · WAL(WriteAheadLog)介绍

概述

在RocksDB中每一次数据的更新都会涉及到两个结构,一个是内存中的memtable(后续会刷新到磁盘成为SST),第二个是WAL(WriteAheadLog)。
本篇文章主要就是来介绍WAL.

阅读全文

Lua源码剖析(五)

这次主要来分析lua的gc。

首先lua中的数据类型包括下面9种,ni, Boolean, number, string, table,user data, thread , functions 以及 lightusedata.其中 string, table,thread , function 是会被垃圾回收管理的,其他的都是值存在。

因此我们来看对应的GC数据结构.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
  
#define CommonHeader GCObject *next; lu_byte tt; lu_byte marked

typedef struct GCheader {

CommonHeader;

} GCheader;

union GCObject {

GCheader gch;

union TString ts;

union Udata u;

union Closure cl;

struct Table h;

struct Proto p;

struct UpVal uv;

struct lua_State th; /\* thread \*/

};

我们可以看到在lua中字符串,userdata, thread, table ,string, thread(以及Upval, proto) 都会被垃圾回收管理。这里比较关键的就是GCheader这个结构体,我们可以看到这个结构体其实就是一个链表,也就是说所有的gc对象都会被链到一个链表中,其中tt表示当前对象的类型,在lua中包括下面这些类型:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
  
#define LUA_TNIL 0

#define LUA_TBOOLEAN 1

#define LUA_TLIGHTUSERDATA 2

#define LUA_TNUMBER 3

#define LUA_TSTRING 4

#define LUA_TTABLE 5

#define LUA_TFUNCTION 6

#define LUA_TUSERDATA 7

#define LUA_TTHREAD 8

而marked表示当前对象的状态(涉及到gc算法,后续会详细分析),状态位包括下面这些:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
  
#define WHITE0BIT 0

#define WHITE1BIT 1

#define BLACKBIT 2

#define FINALIZEDBIT 3

#define KEYWEAKBIT 3

#define VALUEWEAKBIT 4

#define FIXEDBIT 5

#define SFIXEDBIT 6

#define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT)

阅读全文

Lua源码剖析(四)

前面三篇请看我前面的 blog

这篇主要来分析lua的虚拟机的实现,我看的代码依旧是5.1

因此首先从luaL_loadfile开始,这个函数我们知道是在当前的lua state加载一个lua文件,其中第二个参数就是filename。

其中LoadF结构很简单,它用来表示一个load file:

struct LoadF {
1
2
3
4
5
6
7
8
    
int extraline;

FILE *f;

char buff[LUAL_BUFFERSIZE];

} LoadF;

其中会使用fopen来打开对应的文件名,然后根据第一个字符来判断是否是注释(#),如果是则跳过

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
      
lua_pushfstring(L, "@%s", filename);

lf.f = fopen(filename, "r");

if (lf.f == NULL) return errfile(L, "open", fnameindex);

}

c = getc(lf.f);

if (c == ‘#’) { /\* Unix exec. file? \*/

lf.extraline = 1;

while ((c = getc(lf.f)) != EOF && c != ‘\n’) ; /\* skip first line \*/

if (c == ‘\n’) c = getc(lf.f);

}

阅读全文