☰
JanusGraph 实战:基于 Cassandra CQL 存储后端与 Elasticsearch 索引后端的示例应用
2026/10/12 1:40:45 网站建设 项目流程
  • 图数据库
  • 分布式数据库
  • 后端

【免费下载链接】janusgraph

JanusGraph: an open-source, distributed graph database

项目地址:https://gitcode.com/gh_mirrors/ja/janusgraph
点击查看免费下载

导读

本文以 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.JanusGraphFactoryorg.janusgraph.core.JanusGraphFactory
storage.backend存储后端类型,取cql即启用 Cassandra CQL 存储后端cql
storage.cql.keyspaceJanusGraph 在 Cassandra 中使用的 keyspace 名称jgex
storage.hostnameCassandra 服务地址127.0.0.1
index.jgex.backend索引后端类型,elasticsearch表示启用 Elasticsearch 混合索引elasticsearch
index.jgex.index-nameJanusGraph 在 Elasticsearch 中使用的索引名jgex
index.jgex.hostnameElasticsearch 服务地址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()方法定义了完整的应用生命周期:

  1. 打开并初始化图:openGraph()调用ConfigurationUtil.loadPropertiesConfig加载 properties,再通过 TinkerPop 的GraphFactory.open(conf)创建 JanusGraph 实例;
  2. 定义 Schema:createSchema()在写数据前先建立图模式;
  3. 构建图结构:createElements()写入顶点、边与属性(即经典的"诸神之图" Graph of the Gods 数据);
  4. 查询验证:readElements()执行若干 Gremlin 遍历查询;
  5. 循环更新与再查询:随机休眠 500-1000ms 后执行updateElements()/readElements(),共 3 轮;
  6. 删除元素:deleteElements()删除指定顶点(连带其入射边);
  7. 关闭图: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

项目地址:https://gitcode.com/gh_mirrors/ja/janusgraph
点击查看免费下载

相关推荐

上一篇:如何让macOS原生支持200+视频格式预览:QuickLookVideo终极指南
下一篇:Komodo代码覆盖率报告:确保核心功能全面测试

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询