Oracle Berkeley DB Java Edition
Oracle Berkeley DB Java 版是一个开源、可嵌入的事务性存储引擎,完全用 Java 编写。它充分利用 Java 环境来简化开发和部署。Oracle Berkeley DB Java 版的架构为读密集型和写密集型工作负载提供了非常高的性能和并发性。
Oracle Berkeley DB Java 版存储后端与 JanusGraph 在同一个 JVM 中运行,并在单机上提供本地持久性。因此,BerkeleyDB 存储后端要求所有图数据都适合本地磁盘,并且所有频繁访问的图元素都适合主内存。这使得在通用硬件上,图的实际限制为 10 到 100 亿个顶点。然而,对于这种大小的图,BerkeleyDB 存储后端表现出高性能,因为所有数据都可以在同一个 JVM 中本地访问。
BerkeleyDB JE 设置
由于 BerkeleyDB 与 JanusGraph 在同一个 JVM 中运行,连接两者只需要简单的配置,无需额外设置
JanusGraph g = JanusGraphFactory.build().
set("storage.backend", "berkeleyje").
set("storage.directory", "/data/graph").
open();
在 Gremlin 控制台中,您无法定义变量 conf 和 g 的类型。因此,只需省略类型声明即可。
BerkeleyDB 特定配置
除了通用的 JanusGraph 配置选项外,有关所有 BerkeleyDB 特定配置选项的完整列表,请参阅配置参考。使用 SHARED_CACHE 配置的 BerkeleyDB,多个图将更好地利用内存,因为缓存 LRU 算法应用于共享缓存的所有图中的所有信息。
配置 BerkeleyDB 时,建议考虑以下 BerkeleyDB 特定配置选项
- transactions:启用事务并检测冲突的数据库操作。注意:虽然禁用事务可以提高性能,但如果多个 JanusGraph 实例与同一个 BerkeleyDB 实例交互,可能会导致不一致甚至损坏数据库。
- cache-percentage:分配给 BerkeleyDB 用于其缓存的 JVM 堆空间(通过 -Xmx 配置)的百分比。尝试给 BerkeleyDB 尽可能多的空间,而不会给 JanusGraph 造成内存问题。例如,如果 JanusGraph 只运行短事务,请使用 80 或更高的值。
理想用例
BerkeleyDB 存储后端最适合在通用硬件上处理最多 1 亿个顶点的小到中型图。对于这种大小的图,它可能会比分布式存储后端提供更高的性能。请注意,BerkeleyDB 能够有效处理的并发请求数量也有限,因为它运行在单机上。因此,它不适合有许多并发用户修改图的应用程序,即使该图是小到中型的。
由于 BerkeleyDB 与 JanusGraph 在同一个 JVM 中运行,因此此存储后端非常适合使用 JanusGraph 对应用程序代码进行单元测试。
全局图操作
由 BerkeleyDB 支持的 JanusGraph 支持全局图操作,例如迭代所有顶点或边。但是,请注意,此类操作需要扫描整个数据库,对于较大的图来说,这可能需要大量时间。
为了避免内存不足,建议在迭代大型图时禁用事务(storage.transactions=false)。启用事务要求 BerkeleyDB 获取其正在读取的数据的读锁。在迭代整个图时,这些读锁很容易需要比可用内存更多的内存。
附加 BerkeleyDB JE 配置选项
可以通过利用 storage.berkeleyje.ext 命名空间来设置 JanusGraph 不直接公开的附加 BerkeleyDB JE 配置。
JanusGraph 迭代所有以 storage.berkeleyje.ext. 为前缀的属性。它从每个属性键中删除前缀。在剥离键的其余部分中,任何破折号字符 (-) 都将替换为点字符 (.)。最终字符串将被解释为 com.sleepycat.je.EnvironmentConfig 的参数键。因此,选项 storage.berkeleyje.ext.je.lock.timeout 和 storage.berkeleyje.ext.je-lock-timeout 将被视为相同(即 storage.berkeleyje.ext.je.lock.timeout)。与键关联的值不会被修改。这允许在 JanusGraph 的属性中嵌入任意设置。以下是一个配置片段示例,它使用 storage.berkeleyje.ext. 配置机制自定义了三个 BerkeleyDB 设置
storage.backend=berkeleyje
storage.berkeleyje.ext.je.lock.timeout=5000 ms
storage.berkeleyje.ext.je.lock.deadlockDetect=false
storage.berkeleyje.ext.je.txn.timeout=5000 ms
storage.berkeleyje.ext.je.log.fileMax=100000000
死锁故障排除
在并发环境中,使用 BerkeleyDB JE 存储后端时可能会发生死锁。在多个线程修改相同顶点(包括在受影响顶点之间创建边)的用例中,处理死锁可能很复杂。有关此主题的更多见解可在 GitHub 问题 #1623 中找到。
一些用户建议以下配置来处理死锁
storage.berkeleyje.isolation-level=READ_UNCOMMITTED
storage.berkeleyje.lock-mode=LockMode.READ_UNCOMMITTED
storage.berkeleyje.ext.je.lock.timeout=0
storage.lock.wait-time=5000
ids.authority.wait-time=2000
tx.max-commit-time=30000