`

将 Oracle Berkeley DB 用作 NoSQL 数据存储

阅读更多
“NoSQL”是在开发人员、架构师甚至技术经理中新流行的一个词汇。尽管这个术语最近很流行,但令人惊讶的是,它并没有一个普遍认可的定义。

通常来说,任何非 RDBMS 且遵循无模式结构的数据库一般都不能完全支持 ACID 事务,并且因高可用性的承诺以及在横向伸缩环境中支持大型数据集而普遍被归类为“NoSQL 数据存储”。鉴于这些共同特征(与传统的 RDBMS 的特征形成鲜明对比),有人提议非关系(或者简称为 NonRel)是比 NoSQL 更为恰当的术语。

尽管定义冲突仍然存在,但很多人已经意识到将 NoSQL 加到其应用程序体系中的好处。其他人正保持密切关注并评估 NoSQL 是否适合他们。

NoSQL 作为一个类别的发展还导致了大量新数据存储的出现。其中某些新的 NoSQL 产品擅长持久保存像 JSON 这样的文档,某些按照列家族存储排序,其他的则持久保存分布式键值对。尽管更新的产品令人兴奋并且提供了很多好用的功能,但一些现有产品也在奋起直追履行新的承诺。

Oracle Berkeley DB 就是这样一个数据存储。在文本中,我将解释并说明为什么可以将 Berkeley DB 作为 NoSQL 解决方案包括在体系中以及具体实现方式。本文重点关注 Berkeley DB 围绕 NoSQL 的特性,因此不会详尽涵盖 Berkeley DB 的所有功能和特性。

Berkeley DB 要素
基本上,键值存储 Berkeley DB 有三种不同风格:

Berkeley DB — 用 C 编写的键值存储。(Berkeley DB 官方文档使用术语键-数据 代替键值。)这是“经典”风格。

Berkeley DB Java 版 (JE) — 用 Java 重新编写的键值存储。可以轻松包含在 Java 堆栈中。

Berkeley DB XML — 用 C 编写,此版本将键值存储进行包装,使其行为类似于一个已建立索引并且经过优化的 XML 存储系统。

(注意:尽管本文没有明确涉及 Berkeley DB JE 或 Berkeley DB XML,但是包括了一些使用 Java API 和基于 Java 的持久性框架来说明 Berkeley DB 功能的示例。)

Berkeley DB 的核心可能很简单,可以将它配置为提供并行非阻塞访问或支持事务,横向扩展为一个主从副本的高可用集群或者以多种其他方式横向扩展。

Berkeley DB 是一个纯存储引擎,不对键值对的隐式模式或结构做任何假设。因此,Berkeley DB 轻松允许在底层键值存储上实现更高级别的 API、查询和建模抽象。这有助于快速高效地存储应用程序特定数据,而不会产生将其转换为抽象数据格式的开销。这种简单却精致的设计所提供的灵活性能够在 Berkeley DB 中同时存储结构化和半结构化数据。

Berkeley DB 可作为内存中存储来运行,以保存少量数据,也可通过快速的内存中缓存配置为大型数据存储。在更高级别抽象(称作环境)的帮助下,可以在一个物理安装中配置多个数据库。一个环境可以有多个数据库。您需要打开一个环境,然后打开一个数据库,向其中写入数据或者从中读取数据。建议您在完成交互后关闭数据库和环境,从而以最佳方式使用资源。

数据库中的每一项都是一个键值对。键通常是唯一的,但是您可以有重复的项。值是通过键来访问的。可以更新检索值并将其保存回到数据库。通过游标对多个值进行访问和迭代。游标使您可以循环遍历值的集合以及同时操纵整个值集合。另外,还支持事务和并发访问。

键值对的键几乎总是充当建立索引的主键。值中的其他属性可充当次索引。在辅助数据库中单独维护次索引。因此,具有键值对的主要数据库有时候也被称作主数据库。

Berkeley DB 作为一个进程中数据存储运行,因此在使用 C、C++、C#、Java 或脚本语言 API 从相应程序中访问它时,您会以静态或动态方式链接到它。

简要介绍之后,下面将就 Berkeley DB 围绕 NoSQL 的特性进行介绍。

灵活的模式
NoSQL 存储的第一个优势是其对定义明确的数据库模式的宽松态度。我们来看看 Berkeley DB 如何实现此特性。

为了理解 Berkeley DB 的功能,建议您试用一下。因此,建议将 Berkeley DB 和 Berkeley DB JE 下载并安装到您的计算机上,这样您能亲自尝试一些示例并跟随本文中其余例证的操作。此处在线提供了下载链接和安装说明。(在本文中,我使用 --enable-java、--enable-sql 和 --prefix=/usr/local 对 Berkeley DB 进行了编译。)与存储、访问机制和 API 有关的基本概念在 Berkeley DB 和 Berkeley DB JE 之间没有太大区别,因此我后面涉及到的大部分内容同样适用于这两者。

除了数据项必须是键值对集合之外,Berkeley DB 本身对数据项的限制非常少。这就使得应用程序可以灵活地使用 Berkeley DB 管理各种格式的数据,包括 SQL、XML 和 Java 对象。您可以通过基础 API、SQL API、Java Collections API 以及 Java Direct Persistence Layer (DPL) 访问 Berkeley DB 中的数据。它允许几种不同存储配置:B 树、散列、队列和 Recno。(Berkeley DB 文档将不同存储机制称作“访问方法”。散列、队列和 Recno 访问方法仅在 Berkeley DB 中可用,在 Berkeley DB JE 或 Berkeley DB XML 中不可用。)

您可以根据具体用例来选择访问机制和存储配置。选择特定的访问方法和存储配置会影响模式。要了解您的选择所造成的影响,您需要先了解您所选的内容。我接下来要谈到访问方法和存储配置。

使用基础 API
基础 API 是低级别 API,使您可以存储、检索和更新数据(即键值对)。这种 API 在几种不同语言绑定之间是类似的。因此,C、C++ 和 Java 的基础 API 是完全相同的。另一方面,DPL 和 Java Collections API 仅作为抽象在 Java API 中提供。

基础 API 可放置、获取和删除键值对。键和值均为字节数组。在存储所有键和数据值之前,会将其序列化为字节数组。您可以使用 Java 的内置序列化程序或 Berkeley DB 的 BIND API 将各种数据类型序列化为字节数组。Java 的内置序列化程序通常执行速度较慢,因此用户必定更喜欢 BIND API。(jvm-serializers 项目对各种替代序列化程序进行基准测试,是用于在 JVM 的不同序列化机制之间分析相对性能的一个很好的参照点。)BIND API 可通过每个序列化类来避免冗余存储类信息,将该信息放在单独的数据库中。通过编写您自己的自定义字节组绑定来提高 BIND API 性能,您可以潜在地提高速度。

作为一个基本示例,您可以定义如下数据值:

import java.io.Serializable;
public class DataValue implements Serializable {
    private long prop1;
    private double prop2;

    DataValue() {
      prop1 = 0;
      prop2 = 0.0;
    }

    public void setProp1(long data) {
      prop1 = data;
    }
   
    public long getProp1() {
      return prop1;
    }
   
    public void setProp2(double data) {
      prop2 = data;
    }
   
    public double getProp2() {
      return prop2;
    }
}

现在,您可以使用两个数据库来存储此数据值,一个数据库存储带有键的值,另一个数据库存储类信息。

使用四个不同步骤来存储数据:

1.首先,除了用于存储键值对的数据库之外的另一个数据库配置为存储类数据,如下所示:

Database aClassDB = new Database("classDB", null, aDbConfig);2.然后,将一个类目录实例化,如下所示:

StoredClassCatalog storedClassCatalog = new StoredClassCatalog(aClassDb);3.建立一个串行条目绑定,如下所示:

EntryBinding binding = new SerialBinding(storedClassCatalog, DataValue.class);4.最终,DataValue 实例如下所示:

DataValue val = new DataValue();
val.setProp1(123456789L);
val.setProp2(1234.56789);
使用您刚创建的绑定映射到 Berkeley DB DatabaseEntry(充当键和值的包装器),如下所示:

DatabaseEntry deKey = new DatabaseEntry(aKey.getBytes("UTF-8"));
DatabaseEntry deVal = new DatabaseEntry();
binding.objectToEntry(val, deVal);
现在,您可以将键值对放入 Berkeley DB 中。

基础 API 支持 put 和 get 方法的几种变体,以允许或不允许重复项和覆盖。(该示例以及本文都不是为了要教您有关如何使用基础 API 的详细语法或语义,因此我将不会涉及更多细节;请参阅这里的文档)。一个要点是,基础 API 允许就存储、检索和删除键值对进行低级操作和自定义序列化。

如果偏向于使用更高级的 API 与 Berkeley DB 进行交互,那么您应使用 DPL。

使用 DPL
直接持久层 (DPL) 提供了熟悉的 Java 持久性框架语义来操纵对象。您可以将 Berkeley DB 视作一个实体存储,对象在其中持久保存,并可对其中的对象进行检索以便更新和删除。DPL 使用批注将类标记为 @Entity。使用实体进行存储的相关联的类被注释为 @Persistent。特定属性或变量可以注释为 @PrimaryKey 和 @SecondaryKey。一个简单的实体可能如下所示:

@Entity
public class AnEntity {

    @PrimaryKey
    private int myPrimaryKey;

    @SecondaryKey(relate=ONE_TO_ONE)
    private String mySecondaryKey;
    ...
}

DPL 将类定义用作定义明确的模式。通过基础 API,我们知道 Berkeley DB 不要求必须符合模式。但对于某些用例,正式的实体定义很有帮助并可为数据建模提供结构化方法。

存储配置
正如前面所提到的,可以通过四种不同类型的数据结构存储键值对:B 树、散列、队列和 Recno。我们来看看它们的效果如何。

B 树。需要对 B 树进行一些简要介绍,但如果您需要查看其定义,请阅读有关 B 树的 Wikipedia 页面 http://en.wikipedia.org/wiki/B-tree。这是一种平衡的树型数据结构,保证其元素经过排序并允许快速顺序访问、插入和删除。键和值可以为任意数据类型。在 Berkeley DB 中,B 树访问方法允许重复项。如果您需要用复杂数据类型作为键,这是一个不错的选择。如果数据访问模式导致访问相邻的记录,这也是一种很好的选择。B 树保存了大量元数据,可以高效地执行。大部分 Berkeley DB 应用程序使用 B 树存储配置。
散列。与 B 树类似,散列也允许以复杂类型作为键。与 B 树相比,散列具有更加线性化的结构。Berkeley DB 散列结构允许重复项。
尽管 B 树和散列均支持复杂键,但是当数据集远超过可用内存大小时,散列数据库的性能通常优于 B 树。这是因为 B 树比散列保存更多的元数据,更大的数据集意味着 B 树元数据可能无法存储在内存中缓存内。在这种极端情况下,B 树元数据以及实际数据记录本身通常必须取自文件,而这会导致每个操作有多个 I/0。散列访问方法旨在最大程度减少访问数据记录所需的 I/O 数量,因此在这些极端情况下,性能可能会优于 B 树。

队列。队列是一组顺序存储的固定长度记录。键被限制为整数类型的逻辑记录编号。记录是按顺序追加,允许极快写入。如果您对 Apache Cassandra 通过向日志进行追加的快速写入印象深刻,那么请尝试采用队列访问方法的 Berkeley DB,您一定不会失望。这些方法还允许从队列的头有效地读取和更新。队列还支持行级锁定。这样即使是在并发处理的情况下,也能保证有效的事务完整性。
Recno。Recno 与队列类似,但是允许可变长度的记录。与队列类似,reco 键也被限制为整数。
不同配置使您可以在集合中存储任意类型的数据。与 NoSQL 类似,没有固定模式(除了您的模型实施的模式)。在极端情况中,您可以在集合中针对两个键分别存储不同的值类型。值类型可以是复杂类,就参数而言,可以表示 JSON 文档、复杂数据结构或结构化数据集。真正的唯一限制是,值应该序列化为字节数组。单个键或单个值最大可达 4GB。

次索引的出现允许根据值属性进行筛选。主数据库不会以表格格式来存储数据,因此不会为稀疏数据集存储非现有属性。如果键值对缺少用于创建索引的属性,次索引会跳过所有此类键值对。一般来说,这种存储方式既紧凑又高效。

对事务的支持
Berkeley DB 是一个非常灵活的数据库,可以打开和关闭许多特性。Berkeley DB 可以在不支持事务的情况下运行,也可以编译为支持 ACID 事务完整性。也许,Berkeley DB 的可塑性使其成为非常适合许多情况的数据存储。在典型的 NoSQL 数据存储中,对事务完整性的支持最差。在不期望 ACID 事务合规性的具有较高可用性的系统中,Berkeley DB 可以关闭事务,像典型的 NoSQL 产品那样工作。但是在其他系统中,它可能很灵活并且支持事务完整性。

尽管我并不打算涉及有关事务的细节,但值得注意的是,像传统 RDBMS 系统一样,支持事务的 Berkeley DB 允许定义事务边界。一旦提交,数据会持久保存到磁盘。为提高性能,您可以使用非持久性提交,这会将写操作提交到内存中日志文件,随后与底层文件系统进行同步。还支持隔离级别和锁定机制。

在数据库关闭之前,同步操作可保证持久文件副本在系统中具有最新的内存中信息。这种同步操作与 Berkeley DB 的事务恢复子系统的组合(假定您已启用了事务)可确保数据库始终返回到一致的事务状态,即使是在应用程序或系统发生故障时。

大型数据集
理论上,Berkeley DB 具有 256TB 的上限,但实际上,通常受运行 Berkeley DB 的计算机的大小限制。截至撰写本文时,Berkeley DB 未证实可在分布式文件系统的帮助下支持跨多台计算机的极大文件。(可借助 Hadoop 分布式文件系统 (HDFS) 等分布式文件系统的帮助管理超过单个节点大小的文件。)Berkeley DB 在本地文件系统上的性能优于在网络文件系统上的性能。更准确地说,Berkeley DB 依赖文件系统的 POSIX 兼容属性。例如,当 Berkeley DB 调用 fsync() 并且文件系统返回时,Berkeley DB 假定数据已写入到持久介质。出于性能原因,分布式文件系统通常不保证自始至终完成向持久介质的写入。

所支持的最大 B 树深度为 255。键和值的长度通常受可用内存的限制。

横向扩展
Berkeley DB 复制遵循主从模式。在此类模式中,有一个主节点和多个从属节点(或副本)。但是,主节点的选择不是静态的,并且不建议手动选择。复制集群中的所有参与节点都要经历一个选举过程以选出主节点。具有最新日志记录的参与节点将成为获胜者。如果具有绑定,那么优先级用于选择主节点。选举过程基于行业标准的符合 Paxos 的算法。

复制具有很多好处,包括:

提高读性能 — 可从多个副本节点中读取数据极大提高了读性能。

提高可靠性 — 有了副本实例,就可以在发生节点故障和数据损坏时提供更好的故障转移选择。

提高持久性 — 您可以放宽对主节点的持久性保证以避免过多地对磁盘进行写入操作,这通常需要昂贵的 I/O。在集群环境中,通过将写入提交到多个节点(即使未写入到磁盘)这一事实增强了持久性。

提高可用性 — 由于有多个节点并且对磁盘进行异步写入,即使在主节点负载过高的情况下,副本节点仍可继续提供服务。

总结
毫无疑问,Berkeley DB 作为一个强健、可伸缩的 NoSQL 键值存储非常合格;Amazon 的 Dynamo、Project Voldemort、MemcacheDB 和 GenieDB 使用 Berkeley DB 作为底层存储就是支持这一观点的进一步证据。围绕 Berkeley DB 性能一直存在一些恐惧,尤其是下面这两个在线发布的比较基准测试:

http://www.dmo.ca/blog/benchmarking-hash-databases-on-large-data/

http://stackoverflow.com/questions/601348/berkeleydb-vs-tokyo-cabinet

但是,很多运行中的系统证明了 Berkeley DB 的强大。其中许多系统经过了仔细的调整和应用程序编码改进,已经获得了出色的可伸缩性、吞吐量和可靠性结果。效法这些系统,Berkeley DB 无疑可用作可伸缩的 NoSQL 解决方案。


--------------------------------------------------------------------------------

Shashank Tiwari 是 Treasury of Ideas(一家技术驱动的创新和价值优化公司)的创始人兼 CEO。作为一名经验丰富的软件开发人员和架构师,他精通大量技术。他是国际认可的演讲者、作者和导师。作为数种 JCP (Java Community Process) 规范的专家组成员,他一直积极参与规划 Java 的未来。他还代表了 NoSQL 和云计算领域的心声,是 RIA 社区公认的专家。
分享到:
评论

相关推荐

    Berkeley DB Java Edition 5.0.73

    Berkeley DB Java Edition(简称BDB JE)是一款由Oracle公司开发的高性能、轻量级的NoSQL数据库系统。它以其高效能、可扩展性和可靠性在处理大规模数据存储时受到广泛欢迎,尤其是在Google这样的大型互联网公司中,...

    Java嵌入式NoSQL数据库之Berkeley DB Java Edition

    Berkeley DB Java Edition(简称BDB JE)是一种高性能、轻量级的嵌入式数据库系统,由Oracle公司开发,广泛应用于需要快速数据存储和检索的应用场景。它并非传统的关系型数据库管理系统(RDBMS),而是一种键值对...

    libdb5:根据Berkeley数据库许可获得许可的Oracle Berkeley DB的最新版本

    该存储库基于Oracle Berkeley DB 11g第2版,库版本11.2。(5.3.28)-开源版本Berkeley DB的最新版本,该版本已获得Berkeley数据库许可(也称为Sleepycat软件产品许可)的许可。 从下一个版本12.1。(6.0.20)开始,...

    NoSQL数据管理技术

    文章中提到的几种典型的NoSQL产品,如Oracle BerkeleyDB、Kyoto Cabinet、Voldemort和Redis等,它们分别代表了NoSQL技术的不同类别和特点。Oracle BerkeleyDB是一个嵌入式的键值存储系统;Kyoto Cabinet是一个轻量级...

    Oracle NoSQL Database_2013.12

    Understand Oracle NoSQL Database architecture and the underlying data storage engine, Oracle Berkeley DB Install and configure Oracle NoSQL Database for optimal performance Develop complex, ...

    Berkeley_DB_Java_Edition_使用手册

    - **数据日志与事务日志合并**:与C版本不同,JE将数据日志和事务日志合并存储在同一文件中。 - **日志清理机制**:JE Cleaner负责清理不再使用的日志文件空间,如记录被删除或更新后留下的空白空间。清理操作并非...

    Berkeley DB

    Berkeley DB 具有高效的内存管理机制,能够将数据存储在内存中,实现快速的读写操作。当内存中的数据超出物理内存容量时,它会使用磁盘空间作为虚拟内存,通过页缓存策略自动管理数据的读取和写入。 ### 3. **事务...

    Oracle NoSQL 白皮书简介.docx

    Oracle NoSQL数据库在Oracle Berkeley DB Java Edition高可用性存储引擎的基础上,增加了分布式服务层。这一层负责协调跨节点的数据操作,提供了一种透明的方式来管理和分发数据,确保数据的正确性和一致性。 **3. ...

    Dbm NoSQL KyotoCabinet 的介绍

    这种集成使得MySQL能够利用BerkeleyDB的一些特性,如高效的数据存储和高并发事务处理能力。 #### BerkeleyDB的客户 BerkeleyDB因其稳定性和高性能而在多个领域得到广泛应用,例如: - **金融行业**:用于交易系统...

    BerkeleyDB的示例:BerkeleyDB的STL-интерфейсаПримерыиспользования

    BerkeleyDB(简称BDB)是由Oracle公司开发的一款开源、嵌入式、事务型数据库系统,广泛应用于需要高速本地数据存储的场景。它支持多种编程语言,包括C、C++、Java等,并且提供了一个STL(Standard Template Library...

    bdb-18.1.40.zip

    - **高速存取**:Berkeley DB的核心特性之一就是其内存数据库引擎,它允许将数据完全驻留在内存中,显著提高了数据读写速度。这种设计使得BDB在处理高并发和实时数据更新时表现出色。 - **缓存管理**:BDB通过智能...

    Oracle Exadata 2更换硬件供应商No SQL和非关系数据亮点频出.pdf

    此外,甲骨文还发布了面向关系数据的Oracle Berkeley DB 4.5和面向XML数据的Oracle Berkeley DB产品,显示出公司在这方面的研发方向。 6. 开源软件和开发者社区的影响:Sun公司计划推出Java的在线商店,以及将推出...

    大云NOSQL系统设计思考 --NOSQL在电信行业的应用 高清完整中文版PDF下载

    - **分布式存储方案**:利用NoSQL的分布式特性,将数据分散存储到多个节点上,减轻单一节点的压力。 - **分层存储架构**:结合冷热数据的特点,采用不同的存储策略,如使用高速内存作为缓存层,SSD作为热数据存储层...

    Oracle大数据你准备好了吗

    它支持键值对的数据模型,并构建于Berkeley DB之上。Oracle NoSQL数据库的特点是动态数据模型、高度可伸缩性和高可用性,通过透明负载平衡,可以高效地进行数据读写操作。Oracle NoSQL数据库可以使用NoSQL驱动程序...

    dwmclary-blueprints-oracle-nosqldb-40d978d.zip

    Oracle NoSQL,顾名思义,这是甲骨文的NoSQL数据库,基于Java版本的Berkeley DB,主要面向“需要处理海量数据、不确定数据的架构、想采集更多的流媒体数据的客户”。 Blueprints是一组针对属性图数据模型的接口、...

    Redis学习手册

    BerkeleyDB 在被 Oracle 收购之前曾作为 MySQL 的存储引擎,由此可以预见,该产品拥有极好的并发 伸缩性,支持事务及嵌套事务,海量数据存储等重要特征,在用于存储实时数据方面具有极高的可用价值。 然而需要指出的...

    c#几种常用数据库封装

    其次,BerkeleyDB是另一种非关系型数据库(NoSQL),由Oracle公司提供。它主要用于构建高性能、高可用性的数据存储解决方案,尤其适合大量小数据项的应用。BerkeleyDB提供了B树和哈希表两种数据结构,C#中可以通过...

    二、大数据与分布式.pdf

    常见的Key-Value NoSQL数据库包括Redis、Tokyo Cabinet Tryant和Oracle Berkeley DB。 2. 基于Column Family存储的NoSQL数据库 Column Family将Value设计得更精细,由多个属性列组成,形成多层嵌套映射。这种结构常...

    OGG_BigData_Windows_x64_12.3.2.1.0.zip

    "libdb61.dll"是Oracle Berkeley DB的动态链接库,可能用于存储GoldenGate的元数据或者临时数据。 "PocoFoundation64.dll"是Poco库的64位版本,Poco是一组C++类库,常用于网络通信、文件系统操作、时间日期处理等,...

Global site tag (gtag.js) - Google Analytics