Berkeley 四种产品如何选择?
Berkeley 四种产品如何选择?
四种产品综览
Berkeley 可供选择的四款产品:
- DS: 简单的、支持单写单读的数据存储;
支持高并发,多进程同时读操作;不支持锁,这就意味着当程序在进行更新和读操作同时进行的时候,他无法保证数据的正确性;
DS适用于只读类应用或者程序方面能保证同一时间只有不操作一个线程在进行更新数据; - CDS:支持多读单写;内建并发支持,提供锁机制;
- TDS:提供支持事务的数据存储,支持完整的ACID特性,支持数据恢复;
- HA:提供高可用性的解决方案,支持数据主从同步;(需要有事务支持)
Concurrent Data Store (CDS)
- 支持多读单写;
- 内建并发支持,提供锁系统;
- CDS适合于大量查询请求下需要支持并发更新的应用;
CDS适用于多读单写的应用场景,当使用CDS的时候,仅需要 DB_INIT_MPOOL | DB_INIT_CDB 这两个子系统,不应该启用任何其他子系统,比如 DB_INIT_LOCK、DB_INIT_TXN、DB_RECOVER 等。
由于CDS并不启动lock子系统,所以使用CDS无需检查deadlock,但下面的几种情况会导致线程永远阻塞:
- 混用DB handle和cursor(此时同一thread会有两个locker竞争)。
- 当打开一个write cursor的时候,在同一个线程里有其他的cursor开启。
- 不检查BDB的错误码(当一个cursor错误返回时,必须关闭这个cursor)。
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:
- 期望对value部分也建立索引,比如需要secondary indices,多表之间join
- 多个进程并发读写数据库(但需要注意的是,在高并发情况下,比如8进程每秒1000读请求几条写请求,你在解决死锁问题上花费的时间也许会让你痛不欲生)
- 事务性、HA
参考:
Berkeley 四种产品如何选择?的更多相关文章
- php 四种基础算法 ---- 选择排序法
2. 选择排序法: 选择排序法思路: 每次选择一个相应的元素,然后将其放到指定的位置 代码: function select_sort($arr) {//实现思路 双重循环完成,外层控制轮数,当前的最 ...
- (转载)eclipse插件安装的四种方法
eclipse插件安装的四种方法 Eclipse插件的安装方法 1.在eclipse的主目录(ECLIPSE_HOME, 比如在我的机器上安装的目录是:D:\eclipse)有一个plugins的目录 ...
- eclipse插件安装的四种方法
Eclipse插件的安装方法 1.在eclipse的主目录(ECLIPSE_HOME,比如在我的机器上安装的目录是:D:\eclipse)有一个plugins的目录,这种方法的插件安装非常简单,只要将 ...
- Apache Flink on K8s:四种运行模式,我该选择哪种?
1. 前言 Apache Flink 是一个分布式流处理引擎,它提供了丰富且易用的API来处理有状态的流处理应用,并且在支持容错的前提下,高效.大规模的运行此类应用.通过支持事件时间(event-ti ...
- php 冒泡 快速 选择 插入算法 四种基本算法
php四种基础算法:冒泡,选择,插入和快速排序法 来源:PHP100中文网 | 时间:2013-10-29 15:24:57 | 阅读数:120854 [导读] 许多人都说 算法是程序的核心,一个程序 ...
- php四种基础算法:冒泡,选择,插入和快速排序法
转自:http://www.php100.com/html/php/rumen/2013/1029/6333.html 许多人都说 算法是程序的核心,一个程序的好于差,关键是这个程序算法的优劣.作为一 ...
- Java四种排序:冒泡,选择,插入,二分(折半插入)
四种排序:冒泡,选择,插入,二分(折半插入) public class Test{ // public static void main(String[] args) { // Test t=new ...
- golang实现四种排序(快速,冒泡,插入,选择)
本文系转载 原文地址: http://www.limerence2017.com/2019/06/29/golang07/ 前面已经介绍golang基本的语法和容器了,这一篇文章用golang实现四种 ...
- php四种基础算法:冒泡,选择,插入和快速排序法PHP基础教程
许多人都说 算法是程序的核心,一个程序的好于差,关键是这个程序算法的优劣.作为一个初级phper,虽然很少接触到算法方面的东西.但是对于冒泡排序,插入排序,选择排序,快速排序四种基本算法,我想还是要掌 ...
随机推荐
- shell脚本小技巧
输入参数错误时,退格会出现^H,这个时候只要在脚本顶部加一条语句:stty erase ^h就可以了 #!/bin/sh stty erase ^h
- SQLServer学习笔记<>相关子查询及复杂查询
二.查询缺少值的查询 在这里我们加入要查询2008年每一天的订单有多少?首先我们可以查询下订单表的订单日期在2008年的所有订单信息. 1 select distinct orderdate,coun ...
- mysql使用索引扫描来做排序
mysql有两种方式可以生成有序的结果,通过排序操作或者按照索引顺序扫描,如果explain的type列的值为index,则说明mysql使用了索引扫描来做排序(不要和extra列的Using ind ...
- Winform中如何实现子窗体刷新父窗体
原理:利用委托和事件,本文将以图文并茂的例子讲述,告诉我们So Easy --------------------------------------------------------------- ...
- Ubiquitous Religions 分类: POJ 2015-06-16 17:13 11人阅读 评论(0) 收藏
Ubiquitous Religions Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 26678 Accepted: ...
- office软件
32位系统office2013: http://pan.baidu.com/s/1bnCqMZ1 64位系统office2013: http://pan.baidu.com/s/1i33rdHF vi ...
- 分页sql
/// <summary> /// 根据页数分页 /// </summary> /// <param name="page"></para ...
- corefile的设置与使用
一.简介 corefile是Linux下程序崩溃时生成的文件,可以用来分析程序崩溃的原因,因为它内部包含了程序崩溃时的堆栈信息. 二.corefile的设置 默认情况下,程序崩溃是不会生成corefi ...
- Servlet基础(下)
10.Servlet定义初始化参数必须使用web.xml中的init-param/para-name和 para-value元素;11.ServletConfig对象的getInitParameter ...
- div+css基础
Div+css技术 Div是用于存放文字,图片,元素的容器 Css 是用于指定存放在div中的内容如何显示,包括内容的位置和外观(层叠样式表) Html 文件 <!--必须引入的文件--> ...