这是位于零层主题memtable相关实现下的一层主题,预扩展二层主题:函数MakeRoomForWrite作用及其相关实现。
Put和Delete接口都通过调用Write函数来实现,这两个接口函数将需要插入或删除的数据打包进WriteBatch
中,然后传递给Write
函数,如下图:
介绍涉及到的类:WriteOptions
和WriteBatch
:WriteOptions
类只有一个bool成员,用来指示是否将本次写入内存的数据对应的log信息立即刷入磁盘而不是放在缓存中等待批量刷入。WriteBatch
内部有一个std::string
的成员,其按照一定格式存储了多个需要Put或者Delete的key/value对(对于Delete来说只有key)。该成员的结构如下:
在Write
函数中,首先初始化一个Writer对象,并持有传入的batch对象,将其push进writers_中。
Write
类型持有一个WriteBanch
指针,并拥有一些指示变量和同步设施,用以在多个线程调用Put/Delete操作时同步写入的WriteBatch
。
writers_是DBImpl
的一个成员,其记录了一系列Writer
对象,并通过Writer
本身的同步方式使得多个线程的write请求能依次被处理。
注:每个获得锁的write请求会取出尽量多的write数据合并成一个,整体写入内存中,因此被唤醒后的write首先检测本个write是不是已经被取出并写入内存,如果是的话直接退出。代码如下:
当取得锁之后调用函数MakeRoomForWrite
,这个函数内部做了很多工作,这里留作下一层扩展,暂且不细究。此函数的作用主要是确保当前memtable有足够的空间写入,如果空间不够的话需要将现在的mem变为imem并写入磁盘,生成新的mem,即进行一次minor compaction。
确保mem中有足够内存空间容纳本批写入数据操作后,获取最新的全局sequence,并尽量取出当前writers_中的batch合并成一个,作为整体写入内存中。合并操作通过BuildBatchGroup
函数完成。假如有三个线程都在进行Put操作,其都将Writer加入到writers_中,然后等待在Writer的cv_上,这时候其中一个线程被唤醒,它会将这三个Writer从writers_中全部取出并打包进一个WriteBatch中,然后将其他两个Writer的done成员改为true,这样当其他两个线程被唤醒后发现done == true,就直接返回。
继续,将全局sequence+1赋予合并后的updates,然后根据写入键值对的个数计算新的sequence。
这里涉及到类WriteBatchInternal
,这个类内部封装了一些静态函数,用来编码和解码WriteBatch
类中的数据。
在执行真正的写入操作之前,先将updates数据写入日志中,如果本次write操作是sync的,则调用logfile_->Sync()
将缓存中的数据刷到磁盘。真正插入到mem中是通过函数WriteBatchInternal::InsertInto(updates,mem\_);
完成。这个函数比较简单,通过迭代器将updates中的数据依次插入跳跃列表,此处略过。写入完成后,更新全局sequence。
将本次写入数据对应的Writer全部改为已写入状态,并唤醒其调用线程并让其退出。然后唤醒当前writers_的首元素对应的写入线程,让其继续写入操作。
至此,整个Put操作完成。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。