作者:陈磊

NoSQL是现在互联网Web2.0时代备受关注的技术之一,被用来存储大量的非关系型的数据。Berkeley DB作为一款优秀的Key/Value存储引擎自然也在讨论之列。最近使用BDB来发一个KV系统,并将这段时间的BDB的学习和使用经验记录如下。(项目中使用了BDB的4.8.30版本,本文所有涉及的具体问题都基于该版本)。

1. Berkeley DB的简介

Berkeley DB(BDB)是一个高性能的嵌入式数据库编程库(引擎),它可以用来保存任意类型的键/值对 (Key/Value Pair),而且可以为一个键保存多个数据。Berkeley DB可以支持数千的并发线程同时操作数据库,支持最大256TB的数据。

BDB提供诸如C语言,C++,Java,Perl,Python,Tcl等多种编程语言的API,并且广泛支持大多数类Unix操作系统和Windows操作系统以及实时操作系统(如 VxWorks)。

1991年,Berkeley DB的第一个版发行(Linux系统也在这一年诞生),其最初的开发目的是以新的HASH访问算法来代替旧的hsearch函数和大量的dbm实现,该版本还包含了B+树数据访问算法。

1992年,BSD UNIX第4.4发行版中包含了Berkeley DB1.85版。基本上认为这是Berkeley DB的第一个正式版。

1996年,Sleepycat软件公司成立,提供对Berkeley DB的商业支持。

2006年,Sleepycat被Oracle收购,当时最新版本是4.7.25。

2. 直观了解Berkeley DB软件包

Berkeley DB是一款开源软件,我们可以从Oracle的官方网站得到其源代码包。其源代码目录是由一系列子目录组成,从BDB的实现角度按照功能层次可将它们简单归类,划分如下:

a. DB核心模块(db);

b. 各子系统模块(存储管理子系统:btree/hash/qam;内存池管理子系统:mp;事务子系统:txn;锁子系统:mutex;日志子系统:log);

c. 操作系统抽象层(os_brew/os_s60/os_windows等);

d. Build目录(build_brew/build_s60/build_windows等);

e. 工具程序(db_archive/db_checkpoint等);

f. 语言API支持;

g. 例子(examples_c/examples_csharp等);

h. 其它;

通过源代码编译安装BDB很简单,代码如下:

cd ./db-4.8.30/build_unix

../disk/configure --prefix=<dir>

make && make install

安装目标目录(/usr/local/BerkeleyDB.4.8)包含四个子目录:

A. bin  一些实用工具

B. docs  文档

C. include 包含了使用BDB库开发程序时的头文件

D. lib  包含了使用BDB库开发程序时需要连接的库文件

3. 如何获得BDB的相关知识

BDB提供里非常详细的文档,可以官方网站获得html或pdf版本的文档。这里对pdf版本的一些文档简介如下:

BDB_Installation.pdf: BDB的安装文档,涵盖了不同操作系统,不同的编译工具,不同编程语言等多方面的详细信息;

BDB_Prog_Reference.pdf: 该文档是使用BDB的开发人员的参考手册,主要从BDB的各种功能和机制的原理进行阐述,供使用BDB作为存储引擎来编写程序的各类程序员(C、Java、C#、Perl)阅读;

BDB-Porting-Guide.pdf: 该文档是给需要将BDB移植到一个新的平台开发人员准备的;

InMemoryDBApplication.pdf: 基于内存的BDB应用的相关知识;

BDB-C_APIReference.pdf: C API参考手册,跟BDB_Prog_Reference.pdf结合使用;

BerkeleyDB-Core-C-GSG.pdf: 为C语言开发人员提供的BDB的入门手册;

BerkeleyDB-Core-C-Txn.pdf: 为C语言开发人员提供的BDB事务方面的手册;

Replication-C-GSG.pdf: 为C语言开发人员提供的BDB复制方面的手册;

4. 以上对源码目录的分类是从实现角度按照层次进行划分的,如果从BDB的功能模块,或者说是从系统结构角度进行划分,可将其分为几个子系统:

存储管理子系统 (Storage Subsystem)

内存池管理子系统 (Memory Pool Subsystem)

事务子系统 (Transaction Subsystem)

锁子系统 (Locking Subsystem)

日志子系统 (Logging Subsystem)

5. 以上的五个子系统完成了BDB作为一个Database所需要的大部分功能,如何驾驭以上子系统来完成我们需要的任务是关键。像MySQL这种独立的RDBMS,我们可以通过配置和SQL语句来控制和使用它的各种功能。由于BDB是一个嵌入式的数据库,最终还是需要程序员通过调用API来完成。所以要使用好BDB,需要先了解其原理,然后在合适的位置上调用合适的API。

写一个BDB程序的一般步骤:

a. 创建、设置和打开Environment;b. 创建、设置和打开Database;c. 访问Database;d.关闭Database;e. 关闭Environment。

此处的Database是从属于Environment,即db是在env这个环境上面建立起来的。为了便于快速把握重点,可以用BDB跟一般的RDBMS做个类比,这里的Database相当于数据表,Environment相当于数据库。

DB_ENV *dbenv;

DB *dbp;

int ret;

if ((ret = db_env_create(&dbenv, 0)) != 0) {

fprintf(errfp, "%s: %s\n", progname, db_strerror(ret));

return (1);

}

dbenv->set_errfile(dbenv, errfp);

dbenv->set_errpfx(dbenv, progname);

if ((ret = dbenv->set_cachesize(dbenv, 0, 64 * 1024, 0)) != 0) {

dbenv->err(dbenv, ret, "set_cachesize");

dbenv->close(dbenv, 0);

return (1);

}

(void)dbenv->set_data_dir(dbenv, data_dir);

if ((ret = dbenv->open(dbenv, home, DB_CREATE | DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_TXN, 0644)) != 0) {

dbenv->err(dbenv, ret, "environment open: %s", home);

dbenv->close(dbenv, 0);

return (1);

}

if ((ret = db_create(&dbp, dbenv, 0)) != 0){

fprintf(errfp, "%s: %s\n", progname, db_strerror(ret));

return (1);

}

if ((ret = dbp->open(dbp, NULL, "exenv_db1.db", NULL, DB_BTREE, DB_CREATE,0644)) != 0){

fprintf(stderr, "database open: %s\n", db_strerror(ret));

return (1);

}

if ((ret = dbp->close(dbp, 0)) != 0) {

fprintf(stderr, "database close: %s\n", db_strerror(ret));

return (1);

}

if ((ret = dbenv->close(dbenv, 0)) != 0) {

fprintf(stderr, "DB_ENV->close: %s\n", db_strerror(ret));

return (1);

}

return (0);

数据文件:

一个BDB的实例会产生数据存储文件,数据文件的目录由dbenv->set_data_dir(dbenv, data_dir);这条语句来指定。涉及的文件类型有:Data Files,Log Files,Region Files,Temporary Files。

Data Files:数据文件,存储实际的数据;

Log Files:日志文件;

Region Files:是各个子系统保存信息的文件,如果在Env中设置了DB_PRIVATE选项,这些信息是被一个进程私有,即它们保存在内存中,这些文件在此种情况下不产生;

Temporary Files: 临时文件,特使情况会被创建;

数据的存数格式:

Berkeley DB提供了以下四种文件存储方法:哈希文件、B树、定长记录(队列)和变长记录(基于记录号的简单存储方式),应用程序可以从中选择最适合的文件组织结构。以上代码通过db->open函数中设置了DB_BTREE这个选项指定其使用B树方式存储。其它的三种存储格式对应的类型为:DB_HASH,DB_QUEUE,DB_RECNO。

事务提交:

BDB中的事务提交有两种方式:DB_AUTO_COMMIT和显式提交事务。如果设置为DB_AUTO_COMMIT,则每步操作多作为单独的事务自动提交;如果需要显示提交,则需要显示调用具体事务相关的begin/end API(相见文档BerkeleyDB-Core-C-Txn.pdf)。

BDB在事务提交时也是遵循先写日志并刷新到磁盘的方式,但是为了提高性能,其又引入了两个选项:DB_TXN_NOSYNC和DB_TXN_WRITE_NOSYNC。DB_TXN_NOSYNC的作用是使BDB在事务提交的时候不严格要求日志到磁盘,刷新与否取决于日志缓冲;DB_TXN_WRITE_NOSYNC会比DB_TXN_NOSYNC稍显严格,其含义是要求事务提交刷新日志,但只是刷到操作系统文件缓存当中。

BDB的事务隔离性级别有三个:READ UNCOMMITED、READ COMMITED、SERIALIZABLE

CheckPoint

执行一个检查点会完成的工作有:Flushes all dirty pages from the in-memory cache to database files;Writes a checkpoint record;Flushes the log to log files;Writes a list of open databases.

调用API DB_ENV->txn_checkpoint(); 即可完成,如果是非DB_PRIVATE的Env,也可以使用BDB自带的工具db_checkpoint。为了避免出现一个检查点提交大量数据的情况,BDB还提供了轻量级刷新脏页的API:DB_ENV->memp_trickle();

Replication

BDB中提供了两种方式来支持复制技术:Replication Base API和Replication Manager。可以说Replication Base API是最基础的API,实现方式灵活,功能强大,但是编码量大;Replication Manager相当于框架,使用方式简单,编码量小。Replication Manager可能能够满足大部分用户的需求,但不是所有需求,所以灵活性不足。如果您的需要是Replication Manager不能满足的,请使用Replication Base API自己实现复制策略。Replication Manager的主从策略有两种:指定主从、自动推举主从。

分区:

BDB的分区机制是从db-4.8.x之后刚引入的新功能,涉及到的API有两个:

DB->set_partition() 设置分区方式,包含了一个分区方式的回调函数,用户可以通过编写代码来自己实现分区方式,非常灵活。(详见API手册BDB-C_APIReference.pdf)

DB->set_partition_dirs() 设置分区目录。(详见API手册BDB-C_APIReference.pdf)

备份:

BDB有三种备份方式:

Offline Backups:离线备份,停服务拷贝数据目录;

Hot Backups:使用API或者BDB自带工具db_backup在DB在使用情况做备份;

Incremental Backups:增量备份;

具体细节详见BerkeleyDB-Core-C-Txn.pdf。

6. 以下是可能获取到Berkeley DB资源的链接:

官方主页:

http://www.oracle.com/database/berkeley-db/db/index.html

产品下载:

http://www.oracle.com/technology/software/products/berkeley-db/index.html

官方开发者文档中心:

http://www.oracle.com/technology/documentation/berkeley-db/db/index.html

Berkeley DB 使用经验总结的更多相关文章

  1. 新浪研发中心: Berkeley DB 使用经验总结

    http://blog.sina.com.cn/s/blog_502c8cc40100yqkj.html NoSQL是现在互联网Web2.0时代备受关注的技术之一,被用来存储大量的非关系型的数据.Be ...

  2. Berkeley DB的数据存储结构——哈希表(Hash Table)、B树(BTree)、队列(Queue)、记录号(Recno)

    Berkeley DB的数据存储结构 BDB支持四种数据存储结构及相应算法,官方称为访问方法(Access Method),分别是哈希表(Hash Table).B树(BTree).队列(Queue) ...

  3. 比Redis更快:Berkeley DB面面观

    比Redis更快:Berkeley DB面面观 Redis很火,最近大家用的多.从两年前开始,Memcached转向Redis逐渐成为潮流:而Berkeley DB可能很多朋友还很陌生,首先,我们简单 ...

  4. Berkeley DB分布式探索

    明天回家就没有网络,今晚就将整个编写过程记录下来.顺带整理思路以解决未能解决的问题. 标题有点托大,想将Berkeley DB做成分布式存储,感觉很高端的样子,实际上就是通过ssh将Berkeley ...

  5. Berkeley DB数据处理

    设计一个结构,利用Berkeley DB完成大数据的存储,备份,查询功能. 已有的储备: 1.Berkeley DB的基本操作. 2.数据转存后数据不丢失. 3.过百GB以上数据的存储. 数据流如下, ...

  6. Berkeley DB

    最近用BDB写点东西,写了挺多个测试工程.列下表,也理清楚最近的思路 1.测试BDB程序,包括打开增加记录,查询记录,获取所有记录.将数据转存mysql 程序的不足,增加记录仅仅只有key和value ...

  7. BDB (Berkeley DB)数据库简单介绍(转载)

    近期要使用DBD,于是搜了下相关的资料,先贴个科普性的吧: 转自http://www.javaeye.com/topic/202990 DB综述DB最初开发的目的是以新的HASH訪问算法来取代旧的hs ...

  8. Oracle Berkeley DB Java 版

    Oracle Berkeley DB Java 版是一个开源的.可嵌入的事务存储引擎,是完全用 Java 编写的.它充分利用 Java 环境来简化开发和部署.Oracle Berkeley DB Ja ...

  9. Berkeley DB基础教程

    一.Berkeley DB的介绍 (1)Berkeley DB是一个嵌入式数据库,它适合于管理海量的.简单的数据.如Google使用其来保存账户信息,Heritrix用其来保存froniter. (2 ...

随机推荐

  1. Spring 与 MyBatis 的整合

    本文讨论 Spring 与 MyBatis 的整合. 在 beans.xml 中我们定义了两个 bean: SqlSessionFactoryBean.SqlSessionTemplate. 1.Sq ...

  2. pushd命令

    1)功能pushd命令常用于将目录加入到栈中,加入记录到目录栈顶部,并切换到该目录:若pushd命令不加任何参数,则会将位于记录栈最上面的2个目录对换位置 2)语法(1)格式:pushd  [目录 | ...

  3. WebApi学习系列

      最近有一些时间,打算学习和整理一下Web API的一些学习资料的翻译工作.以下是对Web API 的大概目录的整理.欢迎更多的朋友一起加入到学习Web API 的队伍中来,如果你想贡献自己的,请联 ...

  4. Python中str.format()字典及list传入详解

  5. UML关系说明文档

    http://blog.csdn.net/suxinpingtao51/article/details/8011335/

  6. Windows下.svn文件夹的最简易删除方法(附linux)

    如果想删除Windows下的.svn文件夹,通过手动删除的渠道是最麻烦的,因为每个文件夹下面都存在这样的文件.下面是一个好办法:建立一个文本文件,取名为kill-svn-folders.reg(扩展名 ...

  7. CPU, PSU, SPU的区别

    It all started in January 2005 with Critical Patch Updates (CPU).  Then Patch Set Updates (PSU) were ...

  8. Shell编程进阶 1.3data命令

    date命令是显示日期时间的命令 date 2016年 01月 01日 星期五 15:05:01 CST 修改时间的选项是 -s date -s "2016-01-01 12:56:10&q ...

  9. MXF文件结构浅析

    MXF是英文Material eXchange Format(素材交换格式)的缩语.MXF是SMPTE(美国电影与电视工程师学会)组织定义的一种专业音视频媒体文件格式.MXF主要应用于影视行业媒体制作 ...

  10. vue 的全局拦截器

    使用拦截器 你可以截取请求或响应在被 then 或者 catch 处理之前 mounted:function(){ Vue.http.inserceptors.push(function(resque ...