- 图数据库
- 分布式数据库
- 后端
【免费下载链接】janusgraph
JanusGraph: an open-source, distributed graph database
导读
本文以 example-cql 示例为线索,完整讲解如何在 JanusGraph 中组合使用Cassandra(CQL 存储后端)与Elasticsearch(混合索引后端):从jgex-cql.properties配置文件逐项解析、Maven 依赖声明,到通过mvn exec:java运行图应用、用-Dcmd=drop清理图数据,最后深入到GraphApp/JanusGraphApp源码,揭示"打开图 → 建 Schema → 写数据 → 查询 → 更新 → 删除 → 关闭"的完整应用生命周期。读完本文,你将能够独立搭建一套 JanusGraph + Cassandra + Elasticsearch 的本地开发环境,并理解混合索引在该组合下的实际工作方式。
技术选型背景:为什么是 Cassandra CQL 与 Elasticsearch
JanusGraph 将图数据存储与索引查询解耦为两层:存储后端(storage backend)负责持久化顶点、边与属性,索引后端(index backend)负责全文检索、数值范围与地理空间查询。本示例选择的两者是生态中非常经典的组合:
- Apache Cassandra是一个面向可扩展性与高可用设计的分布式数据库。Cassandra 提供两种通信协议:Thrift(遗留 RPC 协议)与CQL(原生协议)。JanusGraph 的
cql存储后端即通过 CQL 协议与 Cassandra 通信,这也是当前主流且持续演进的方式。 - Elasticsearch是一个可扩展的分布式搜索引擎,充当 JanusGraph 的混合索引后端(mixed index backend)。
在动手之前,建议先查阅仓库内的版本兼容性矩阵。以当前仓库的 1.2.z 主线为例,兼容范围覆盖 Cassandra 3.11.z / 4.0.z / 5.0.z,以及 Elasticsearch 6.1-6.8.z / 7.y / 8.y / 9.y 与 OpenSearch 2.y / 3.y。务必保证你安装的 Cassandra 与 Elasticsearch 版本落在所选 JanusGraph 版本的支持范围内,这是本示例能够顺利运行的前提。
JanusGraph 配置文件逐项解析
本示例的全部连接配置都集中在jgex-cql.properties中,完整内容如下:
gremlin.graph=org.janusgraph.core.JanusGraphFactory storage.backend=cql storage.cql.keyspace=jgex storage.hostname=127.0.0.1 index.jgex.backend=elasticsearch index.jgex.index-name=jgex index.jgex.hostname=127.0.0.1各配置项的作用:
| 配置项 | 含义 | 本示例取值 |
|---|---|---|
gremlin.graph | 告诉 TinkerPop 的GraphFactory使用哪个工厂类来创建图实例,固定为org.janusgraph.core.JanusGraphFactory | org.janusgraph.core.JanusGraphFactory |
storage.backend | 存储后端类型,取cql即启用 Cassandra CQL 存储后端 | cql |
storage.cql.keyspace | JanusGraph 在 Cassandra 中使用的 keyspace 名称 | jgex |
storage.hostname | Cassandra 服务地址 | 127.0.0.1 |
index.jgex.backend | 索引后端类型,elasticsearch表示启用 Elasticsearch 混合索引 | elasticsearch |
index.jgex.index-name | JanusGraph 在 Elasticsearch 中使用的索引名 | jgex |
index.jgex.hostname | Elasticsearch 服务地址 | 127.0.0.1 |
这里有一个值得注意的设计:配置前缀index.jgex.*中的jgex是索引后端在 JanusGraph 内部的逻辑名称,它通过index.jgex.index-name=jgex与 Elasticsearch 中的物理索引名解耦。更多可用配置项请参考仓库内的配置参考文档。
多图共存:keyspace 与 index-name 的隔离作用
这是本示例 README 强调的一个实用技巧:通过为不同的图提供不同的storage.cql.keyspace与index.jgex.index-name,可以在同一组 Cassandra / Elasticsearch 服务器上共存多张独立的图。例如:
# 图 A storage.cql.keyspace=graph_a index.jgex.index-name=graph_a # 图 B(另一份 properties 文件) storage.cql.keyspace=graph_b index.jgex.index-name=graph_b图数据落在 Cassandra 的不同 keyspace 中,索引数据落在 Elasticsearch 的不同 index 中,二者互不干扰。从源码层面也可以印证这一点:CQLConfigOptions.KEYSPACE声明 keyspace 的默认值为janusgraph,并注明"如果不存在会自动创建";而 Elasticsearch 后端在写入时会把配置的index-name与每个 store 名称拼接成实际的索引名(见ElasticSearchIndex.java中INDEX_NAME_SEPARATOR的处理逻辑)。
Cassandra 与 Elasticsearch 的本地默认假设
jgex-cql.properties假定Cassandra 已安装在本机(localhost)并使用默认配置,Elasticsearch 同理。也就是说:
- Cassandra 通过 CQL 协议在默认端口(9042)监听
127.0.0.1; - Elasticsearch 通过其原生协议在默认端口监听
127.0.0.1。
如果你把 Cassandra 或 Elasticsearch 部署在远程主机、非默认端口或集群环境中,直接修改上述storage.hostname/index.jgex.hostname等项即可,无需改动代码。仓库还提供了一份更完整的服务端组合配置样例 janusgraph-cql-es.properties,其中包含storage.cql.local-datacenter、缓存参数(cache.db-cache、cache.db-cache-size等)与 Elasticsearch 相关的更多选项,可作为生产化调优的参考。
偷懒方案:使用 JanusGraph 预打包发行版
如果你不想分别安装 Cassandra 与 Elasticsearch,JanusGraph 官方提供了预打包发行版(pre-packaged distribution):解压后即可一键启动本地 Cassandra、Elasticsearch 与 Gremlin Server,开箱即用地运行本示例。该方式的具体使用说明见 docs/basics/server.md 中"Using the Pre-Packaged Distribution"一节。
引入 Maven 依赖
本示例的example-cql/pom.xml采用pom打包方式,核心依赖均为runtime作用域。独立项目接入时,需要声明以下依赖。
CQL 存储后端依赖:
<dependency> <groupId>org.janusgraph</groupId> <artifactId>janusgraph-cql</artifactId> <version>${janusgraph.version}</version> <scope>runtime</scope> </dependency>Elasticsearch 索引后端依赖:
<dependency> <groupId>org.janusgraph</groupId> <artifactId>janusgraph-es</artifactId> <version>${janusgraph.version}</version> <scope>runtime</scope> </dependency>此外,示例代码本体位于example-common模块(org.janusgraph:example-common),它同样以runtime作用域被引入。将三者组合后,GraphFactory.open(conf)才能在运行时加载到 CQL 存储后端、Elasticsearch 索引后端与示例应用类。
运行示例:完整应用生命周期
启动命令
在janusgraph-examples聚合目录或仓库根目录下执行:
mvn exec:java -pl :example-cql命令中的-pl :example-cql是 Maven reactor 的模块选择语法,指向 janusgraph-examples 聚合工程下的example-cql模块,因此它必须从聚合目录或仓库根目录运行,这正是 README 中所说"可以在examples或项目目录下运行"的原因。
该命令由janusgraph-examples/pom.xml中配置的exec-maven-plugin驱动:主类固定为org.janusgraph.example.JanusGraphApp(由example.main.class属性注入),启动参数中的${example.config}指向jgex-cql.properties,第二个参数${cmd}默认为空。
应用到底做了什么:从源码看完整流程
示例程序的主体是GraphApp抽象类,其runApp()方法定义了完整的应用生命周期:
- 打开并初始化图:
openGraph()调用ConfigurationUtil.loadPropertiesConfig加载 properties,再通过 TinkerPop 的GraphFactory.open(conf)创建 JanusGraph 实例; - 定义 Schema:
createSchema()在写数据前先建立图模式; - 构建图结构:
createElements()写入顶点、边与属性(即经典的"诸神之图" Graph of the Gods 数据); - 查询验证:
readElements()执行若干 Gremlin 遍历查询; - 循环更新与再查询:随机休眠 500-1000ms 后执行
updateElements()/readElements(),共 3 轮; - 删除元素:
deleteElements()删除指定顶点(连带其入射边); - 关闭图:
closeGraph()依次关闭GraphTraversalSource与Graph。
该类的 Javadoc 注释将上述步骤总结为:"Open and initialize the graph → Define the schema → Build the graph → Run traversal queries → Make updates → Close the graph"。
子类JanusGraphApp则使用 JanusGraph 特有 API 定义 Schema:
- 属性键(PropertyKey):
name(String)、age(Integer)、time(Integer)、reason(String)、place(Geoshape); - 顶点标签:
titan、location、god、demigod、human、monster; - 边标签:
father/mother(Multiplicity.MANY2ONE)、lives(以reason为 signature)、pet、brother、battled; - 组合索引:
nameIndex(精确匹配查询使用); - 混合索引:
vAge(顶点age数值范围查询)、eReasonPlace(边reason+place,全文/地理空间查询)。
其中混合索引只有在配置文件中存在index.jgex.backend时才启用(JanusGraphApp.openGraph()中通过conf.containsKey("index." + mixedIndexConfigName + ".backend")判断),这正体现了"存储后端 + 索引后端"双层架构中 Elasticsearch 承担的角色。由于混合索引存在延迟刷新,createElements()在写数据后会Thread.sleep(10000)等待索引可见。
查询示例:混合索引如何被使用
readElements()中的三类查询分别演示了不同索引的用途:
// 组合索引:按 name 精确查找(Composite Index) g.V().has("name", "jupiter").valueMap(true) // 混合索引:数值范围查询 age >= 5000(Mixed Index / ES) g.V().has("age", P.gte(5000)).values("age")日志输出
example-cql自带的 logback.xml 将根日志级别设为INFO,并单独把com.datastax.driver.core降至WARN,避免 CQL 驱动刷屏。运行后你将在控制台看到opening graph、creating schema、creating elements、reading elements、updating elements、deleting elements、closing graph等关键步骤的日志。
清理图数据:drop 命令
运行示例后,图数据与索引会持久化在 Cassandra 与 Elasticsearch 中。若希望彻底清除,请先停止应用程序,再执行:
mvn exec:java -pl :example-cql -Dcmd=drop-Dcmd=drop通过 exec 插件注入到JanusGraphApp.main的第二个参数。从JanusGraphApp.main的源码可以看到:当drop参数存在时,应用只执行openGraph()与dropGraph();而dropGraph()最终调用JanusGraphFactory.drop(getJanusGraph()),彻底删除存储中的图。相比之下,example-common的 in-memory 后端图数据随进程结束自然消失,无需 drop 操作。
小结
通过example-cql示例,你可以掌握 JanusGraph 最主流的部署组合——Cassandra CQL 存储后端 + Elasticsearch 索引后端:配置层面理解storage.cql.keyspace与index.<name>.index-name的多图隔离机制,依赖层面知道janusgraph-cql与janusgraph-es两个 runtime 依赖的分工,运行层面熟悉mvn exec:java -pl :example-cql与-Dcmd=drop两条命令,源码层面则看清了图应用的完整生命周期与组合/混合索引的创建及查询路径。这套流程可以直接迁移到你自己的 JanusGraph 项目中,只需替换配置文件中的 keyspace、索引名与主机地址即可。
- 图数据库
- 分布式数据库
- 后端
【免费下载链接】janusgraph
JanusGraph: an open-source, distributed graph database
相关推荐
JanusGraph 示例配置实战:BerkeleyDB、Cassandra 与 HBase 存储后端及 Elasticsearch 索引后端组合配置详解
JanusGraph 示例配置实战:BerkeleyDB、Cassandra 与 HBase 存储后端及 Elasticsearch 索引后端组合配置详解 本文
图数据库分布式数据库后端JanusGraph 从 Thrift 后端迁移到 CQL 后端:配置替换与实战指南
JanusGraph 从 Thrift 后端迁移到 CQL 后端:配置替换与实战指南 导读 本指南聚焦于 JanusGraph 存储后端的重大切换:把由旧版 C
图数据库分布式数据库后端JanusGraph 与 Apache Cassandra 集成部署全指南:CQL 存储后端、四种部署模式与云托管实践
JanusGraph 与 Apache Cassandra 集成部署全指南:CQL 存储后端、四种部署模式与云托管实践 本指南以 JanusGraph 官方文档
图数据库分布式数据库后端
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考