计划实现一个开源的KV数据库——Simple DB

实现一个开源KV数据库的想法来源于对目前项目中所使用的K-V数据库使用情况的不满意。

先介绍一下我们的目前项目,作为本文的背景:

较为底层的分布式运行平台,使用C/C++实现的Actor模型(异步消息传递系统)

数据schema简单灵活,使用key-value能够很好表示。

数据库有大量的读写请求,有事务需求,数据丢失容忍度很低。

当前,从众多的KV和NOSQL存储产品中,我们使用了Berkeley DB作为底层的存储引擎。

 

为什么选择BDB呢?

1.与传统的RDBMS相比,简单K-V存储的Berkeley DB(再加入“嵌入式”直接库链接的特性)有着优越的性能,容易满足我们大量读写(尤其是大量写)的需求。

2.作为一个嵌入式的K-V数据库,Berkeley DB历史悠久(目前由Oracle所有),稳定且久经考验,文档丰富,辅助工具全面。这是我们之所以在众多的开源K-V(Nosql)数据库中选择BDB的首要原因:靠谱

3.第三个选择BDB的原因是事务支持:作为为数不多的能够提供ACID事务支持的K-V数据库,BDB对事务支持提供了丰富的支持:从不同的隔离级别、不同的持久化保证以及分布式事务2PC的prepare模型等,可配置程度很高。

 

BDB哪些方面不能达到我们的需求?

1.仍然是性能。作为K-V数据库,BDB的性能依然达不到我们的目标:由于有足够大的内存作为缓存,读操作的性能基本没问题,但写操作(尤其是大量应用的事务写)的性能堪忧。

使用Auto-commit(每条写作为一个独立的事务),一条记录的写延时接近于1~10ms。

显示开启事务后,写操作有了极大改善:10~100us(因为不需要即时sync到硬盘),但事务提交操作依然极为耗时。

有人可能会说,你可以调节BDB事务的持久化保证的程度,比如在提交时设置:

DB_TXN_WRITE_NO_SYNC,在提交时只写log到硬盘,不sync(只有OS Crash才会丢数据)

或者更快一些,使用DB_TXN_NOSYNC,连同步调syscall write的开销都省下来(但App crash可能会丢数据)

我们当前的项目是一个底层的运行时平台,对数据丢失的敏感程度是很高的,不像一些常见的互联网应用。我们既需要事务的Durability支持,也需要高的写性能。

2.我们的数据模型相对简单:Key-Value存储,需要事务的Atomicity支持批量修改,需要事务的Durability保证,可能需要Prepare语义支持分布式事务。

不需要对数据库访问的并发支持。当前核心系统是一个基于线程池的异步系统,数据库的写操作和提交操作应该由独立线程来完成,不应阻塞有限的池中线程。因此我们可以不需要并发支持而使用单独线程操作数据库。

至于事务的Consistency和Isolation以及各种复杂的锁协议(尤其是BDB中恼人的page级别的锁粒度),在不需要并发访问的数据库中也不需要。

这样的需求,或许通过详细的配置和tuning也能在BDB上实现,但BDB毕竟太大太复杂(一方面BDB为了通用的需求,实现复杂,难以了解内部机理;一方面是配置复杂),以至于步履蹒跚。

与其继续钻研BDB的各种配置来适配当前特殊的需求,不如轻装上阵,自己实现一个项目特定的底端存储,由于目标和需求少儿明确,实现起来要简单很多,预期能够获得比BDB更高的性能。

 

这个数据库暂时取名为Simple DB,其主要需求和大致实现如下:

1.Key-Value存储,使用Hash实现(可能需要使用linear hash),不采用实现较为复杂的B+树

2.嵌入式,通过链接方式直接使用,不适用其他IPC。只考虑Linux 2.6平台,暂不考虑其他平台。

3.主要支持get/set/traverse操作

(如果支持delete操作,也不会释放或重新利用文件空间:重利用释放的空间向来是一个复杂的问题,既要保证效率,又要避免碎片。最多提供一个database compress工具进行文件的压缩处理。)

4.每个数据库包括:数据文件,索引文件和日志文件,不支持并发访问。

5.支持事务,但只提供Atomicity和Durability语义。(使用write-ahead logging)

支持跨同一目录下多个数据库的事务,可能会提供事务的prepare语义。

6.暂不考虑replication支持,不支持shading(由应用层自行完成)

 

希望数据库如其名,简单高效。

Keep it simple, stupid!

 

posted @ 2012-01-12 23:09  PromisE_谢  阅读(4407)  评论(1编辑  收藏  举报