Bitcask¶
一个 Bitcask
实例可以看成一个目录,目录下面放了数据文件,而每次操作都会写入到
active
的文件中,当这个文件大小达到一个阈值之后,就新建一个文件,之前的文件只读,不可以再写入数据。
+-------------------------+
| |
| |
| +-------------------+ |
| | active data file | |
| | | |
| +-- /------+ |
| \--------- |
| +--------------------+ |
| | order data file | |
| +--------------------+ |
| +--------------------+ |
| | order data file | |
| +--------------------+ |
| +--------------------+ |
| | order data file | |
| +--------------------+ |
| +--------------------+ |
| | order data file | |
| +--------------------+ |
| |
+-------------------------+
状态为 active 的文件在写入的时候,只能在文件尾部做 append 操作,这样可以减少不必要的磁盘检索。
每一条 K/V 数据的格式也非常简单
|---------------------CRC converage -----------------------------------------|
size of
+-----------------+
| |
| \|/
+-----------------+----------------------------------------------------------------+
| crc | tstamp | k|z | value_sz | key | value |
+----------------------------------------------------------------------------------+
| /|\
| |
+---------------------------------------+
size of
这样,每次写入,都是将一条新的记录
append
到状态为 active
的文件中。即便是
删除
操作也是追加一条特殊的记录。当写入操作完成之后,需要更新保存在 内存 中的一个
keydir
哈希树。
keydir
里面保存着每一个 key
对应的文件,已经这个 key
在文件中的偏移量。
+-------------------------------------------------------------------+
| +----------------------------------------------------------+ |
| key -|file_id | value_sz | value_pos | tstamp | |
| +----------------------------------------------------------+ |
| |
| +----------------------------------------------------------+ |
| key -|file_id | value_sz | value_pos | tstamp | |
| +----------------------------------------------------------+ |
| |
| +----------------------------------------------------------+ |
| key -|file_id | value_sz | value_pos | tstamp | |
| +----------------------------------------------------------+ |
+-------------------------------------------------------------------+
value_post --> 值的位置
发生一次写入操作时, keydir
会随着本地数据的写入而自动更新。老的数据还会保存在硬盘上面,但是之后的读操作都是使用新的
keydir
,后面我们会看见 merge
操作最终会把旧数据移走。