鸿 网 互 联 www.68idc.cn

当前位置 : 服务器租用 > 编程语言开发 > c++ > >

Berkeley 四种产品如何选择?

来源:互联网 作者:佚名 时间:2013-11-29 10:47
Berkeley 四种产品如何选择?四种产品综览 Berkeley 可供选择的四款产品: Concurrent Data Store (CDS) CDS适用于多读单写的应用场景,当使用CDS的时候,仅需要 DB_INIT_MPOOL | DB_INIT_CDB 这两个子系统,不应该启用任何其他子系统,比如 DB_INIT_LOCK、D

Berkeley 四种产品如何选择? 四种产品综览

Berkeley 可供选择的四款产品:

Concurrent Data Store (CDS)

CDS适用于多读单写的应用场景,当使用CDS的时候,仅需要 DB_INIT_MPOOL | DB_INIT_CDB 这两个子系统,不应该启用任何其他子系统,比如 DB_INIT_LOCK、DB_INIT_TXN、DB_RECOVER 等。

由于CDS并不启动lock子系统,所以使用CDS无需检查deadlock,但下面的几种情况会导致线程永远阻塞:

CDS与DS的区别

CDS和DS的区别就在于,当要写db的时候,应该使用DB_WRITECURSOR创建一个write cursor。当这样的write cursor 存在的时候,其他试图创建 write cursor 的线程将被阻塞,直到该 write cursor被关闭。
当write cursor存在的时候,read cursor不会被阻塞;但是,所有实际的写操作,包括直接调用DB->put()或者DB->del()都将被阻塞,直到所有的read cursor关闭,才会真正的写入db。这就是multiple-reader/single-writer的具体工作机制。

CDS中的注意事项

如果使用secondary database,意味着会在同一个cursor下操作两个db,此时如果用CDS,也许必须设置DB_CDB_ALLDB,但这会严重影响性能。

所谓 DB_CDB_ALLDB 是一个非常粗粒度的锁,CDS的锁基于API-layer,默认per-database,但如果设置了DB_CDB_ALL,则是per-environment,这意味着:

整个DB environment下只能有一个write cursor。
当写db的时候,整个DB environment下任何read cursor不可以打开。
读写CDS简单的做法是能用DB handle的地方直接使用DB handle,,没有必要使用CURSOR handle,因为你用DB->put()或者DB->del()来修改数据库时,它内部也是调用了CURSOR handle。当然,如果你要使用CURSOR遍历数据库时,用于写的CURSOR必须设置DB_WRITECURSOR来创建:

DB->cursor(db, NULL, &dbc, DB_WRITECURSOR);
直接调用DB->put()或者DB->del(),或者先使用DB_WRITECURSOR创建CURSOR handle,最终都进入__db_cursor()函数,设置db_lockmode_t mode = DB_LOCK_IWRITE,然后用该mode加锁。但需要注意的是,不能在同一thread下混用DB和CURSOR handle,因为每个CURSOR会分配一个LOCKER,而DB handle也会分配一个LOCKER,两者可能导致self-deadlock。

如果在read lock或者write lock过程中,程序崩溃,这可能导致lock遗留在env中无法释放(可以用db_stat -CA观察到),这种情况下该environment已经损坏,只能删除该environment(删除掉__db.001之类的文件即可),重新创建。

Transactional Data Store (TDS)

TDS:支持锁、支持事务;
TDS是使用BDB的终极方式,它适用于多读多写,并且支持Recoveriablity等任何你能想到的常见数据库特性,或者不如说,只有当你确定需要这些特性的时候,你才应该使用BDB;如果你仅仅想要一个单纯的KV系统,那也许BDB并不适合你。

一般来说,创建TDS Environment的flag如下:

DB_CREATE | DB_INIT_MPOOL | DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_TXN
TDS的任何DB相关的操作都必须是事务性的,包括打开db时,都需要先创建txn:

DB_TXN* txn; int ret = env->txn_begin(env, NULL, &txn, 0); ret = db->open(db, txn, "test.db", NULL, DB_BTREE, DB_CREATE, 0); // 如果使用secondary database, 则associate()调用也需要包含在txn里 ret = db->get(db, txn, &key, &val, 0); ret = db->put(db, txn, &key, &val, 0); if(ret) txn->abort(txn); else txn->commit(txn, 0);

`
如果仅仅有读操作,其实可以无需调用commit,直接abort即可。

如果使用 DB_AUTO_COMMIT 打开db,则关于db handle的操作,不需要额外指定txn参数,此时使用了BDB的autocommit特性。

HA:提供高可用性的解决方案;

HA支持数据复制。这里会区分主从服务器,master机器负责所有的更新操作,并且,更新完成后,由这台机器将更新后的数据复制到slave机器上;
HA对于slave没有结点数量的限制,理论上只要硬件环境支持,可以支持任意多个;
但是在同步的时候有一点需要注意,就是HA结点的同步都是通过master结点复制数据,就是说,master复制完第一个slave之后,再复制到第二个slave;这样的话,如果每次同步的时间较长,则有可能造成第一个slave和最后一个slave在很短的一段时间内查询出的数据不一致;
Maser结点宕机之后,由剩下的slave结点通过投票算法选出新的master结点;如果没有选出master,则不再接收更新操作;

建议

TDS、HA支持的功能多,但是需要付出相应的性能代价;
如果程序没有事务要求,尽量在DS和CDS中进行选择;

BDB是为并发访问设计的,thread-safe,且良好的支持多进程访问。可以看出BDB比一般的KV数据库还是要复杂很多的,如果你需要如下的一些特性,也许你可以考虑BDB:

参考:

BDB产品对比

Berkeley DB的使用

 

网友评论
<