【巨杉数据库SequoiaDB】社区分享 | SequoiaDB + JanusGraph 实践
本文来自社区用户投稿,感谢小伙伴的技术分享
项目背景
大家好!在春节这段时间里,由于一直在家,所以花时间捣鼓了一下代码,自己做了 SequoiaDB 和 JanusGraph 的兼容扩展工作。
自己觉得这个项目还是挺有意思的,本着开源即是美德的想法,我把自己的代码开源出来了,欢迎 JanusGraph 和 SDB 爱好者拍砖,也希望对这块比较感兴趣的朋友,可以和我一起来完善这个项目。
我们团队在做一个项目时,引入了国产数据库 SequoiaDB,感觉效率啊,维护性啊,都比较友好。自己呢,年前也刚好在其他场景需要应用到一些图计算相关的技术,就想着是否可以为 SequoiaDB 加个 JanusGraph 的翅膀。因为根据我的理解,JanusGraph 对存储扩展极度的友好。
(项目地址:https://github.com/ak918808/sequoiadb_for_janusgraph)
JanusGraph 介绍
实际上,在图数据领域里,Neo4j 才是真正处于统治地位的,但是无奈它的社区版本,性能“限(yan)制(ge)”得太过分了,功能也是各种被砍,难以使用在生产环境里。至于企业版,目前也没有专门的预算给到这块的需求。
而看看图数据库里的老二 -- JanusGraph ,Apache 基金会顶级项目,顶着当年明星项目 Titan 的光环,继续忍辱负重地前行。“这个孩子肯定有出息”,我就是这么想的。
如果大家好奇 JanusGraph 的前世今生,可以扒一扒 DataStax(Cassandra 母公司)对 Titan 干了啥。然后一群热爱开源,又相当牛叉的程序猿就独立单干了。反正这个故事听起来,和当年 MySQL 和 MariaDB 相爱相杀的故事差不多,只是 JanusGraph 的下场更加壮烈。
我从 JanusGraph 的官网里找了一个整体的架构图,大家可以看到 JanusGraph 的模块还是挺丰富的,功能也是比较的全面。
JanusGraph 在存储层中,分开了两个部分,一个专门存储数据(Storage Backend)的,另外一个是专门存储索引信息(Extemal Index Backend)的。存储层中这两个模块都设计得非常 open,逻辑比较清晰,简直就是希望大家踊跃尝试的意思。
JanusGraph 的操作语言,使用 Gremlin 语法进行操作。Gremlin 应该算是图计算里面的事实标准,很多的图计算语法,都是基于 Gremlin 进行二次开发的。
JanusGraph 还能够提供基于 Hadoop 啊,Spark 这些大数据的分析框架,为用户提供 OLAP 的服务。
但是最令我感到震惊的是,JanusGraph 竟然还支持事务功能,虽然是非常有限的事务,但确实提供了这个功能,但是需要存储层的产品来支撑事务功能。
JanusGraph 的存储模块,它本身就是按照插件式的形式组成,大家可以从它的源代码的结构就能够看出来。
这种插件方式,在大数据平台里很多产品都是这种设计,Hadoop、Spark、Hive 等,另外,大家能够想到连著名的 MySQL 也是采用这种插件设计吗?这种插件的设计方法,优点就是容易集成,大家可以根据需要,随时扩展它的功能,这个是它社区繁荣的基础,也是它能够更快地衍生出更多场景的基础。
另外一方面,大家是否发现了,JanusGraph 支持的存储产品里,基本都是列存储的,譬如:HBase、Cassandra,都是列簇型的数据库,BerkeleyDB 则是一款K/V 型的数据。
以 HBase 数据库为例,因为它是列簇型的数据库,所以它把所有的内容都存放到了一张表里,通过不同的 Family 来保存,达到 I/O 分离的目的。而且 JanusGraph 向底下的数据库存储数据时,都是采用 Binary 格式进行保存,我看了一下代码,JanusGraph 除了需要保存一些常用的 Int、Boolean、String 类型外,还会保存一些 JanusGraph 自己特殊的类型数据。另外一个比较有意思的地方,可能是 HBase 或者是 Casssandra 数据库的API 特点,JanusGraph 将列的名字也是采用 Binary 格式存储,并且里面使用了 HBase 对 Key 排序的功能来读取数据。
从这些细节来看,JanusGraph 的存储设计都是基于列存储或者是 K/V 型的数据库进行,不知道是由于 Titan 的历史包袱,还是一些其他的考虑。
我自己在阅读 JanusGraph 的存储代码时,主要就是参考 HBase 和 BerkeleyDB 的代码,逻辑比较清晰。
一开始时,为了简单对接 SequoiaDB,我是模仿着 BerkeleyDB 的代码来写的,但是写到后面发现 BerkeleyDB 由于是本地存储,不是 remote 方式,所以很多的参数都是围绕本地的。虽然自己也可以扩展参数,使得可以通过网络连接 SequoiaDB,但是总解决不伦不类,就又转向到 了 HBase 的代码研究上了。
JanusGraph 如何分别出各个存储的呢?实际上,当用户在 Gremlin 中启动 JanusGraph 的服务时,需要指定一个 storage.backend 参数,然后在 JanusGraph 的 core 模块里的 StandardStoreManager 类,就有一个 enum 来区别各个存储产品,应该初始化哪个 manager 类。
大家打开 StandardStoreManager.java 文件,就能够看到以下的 enum 描述。
BDB_JE("org.janusgraph.diskstorage.berkeleyje.BerkeleyJEStoreManager", "berkeleyje"),
CASSANDRA_THRIFT("org.janusgraph.diskstorage.cassandra.thrift.CassandraThriftStoreManager", "cassandrathrift"),
CASSANDRA_ASTYANAX("org.janusgraph.diskstorage.cassandra.astyanax.AstyanaxStoreManager", ImmutableList.of("cassandra", "astyanax")),
CASSANDRA_EMBEDDED("org.janusgraph.diskstorage.cassandra.embedded.CassandraEmbeddedStoreManager", "embeddedcassandra"),
CQL("org.janusgraph.diskstorage.cql.CQLStoreManager", "cql"),
HBASE("org.janusgraph.diskstorage.hbase.HBaseStoreManager", "hbase"),
IN_MEMORY("org.janusgraph.diskstorage.keycolumnvalue.inmemory.InMemoryStoreManager", "inmemory");
JanusGraph 就是通过不同的 storage.beckend 的名字,来判断应该初始化哪个 manager 类。
JanusGraph 关于 HBase 的代码,有好几个文件夹,但是真正核心的类,其实就是 HBaseStoreManager 和 HBaseKeyColumnValueStore 两个类。
HBaseStoreManager 类是这个存储插件的入口类,它初始化了 JanusGraph 和 HBase 之间的连接,并且根据不同的 family 保存不同的连接。每一个 family 连接都会对应一个 HBaseKeyColumnValueStore 实例。
HBaseKeyColumnValueStore 类主要是对数据的存和取的操作,包括将 JanusGraph 的数据转换成 HBase 自身的格式,然后进行保存,或者是查询。
由于 HBase 不支持事务功能,所以 JanusGraph 在 HBase 上直接是关闭了事务功能。这个事情未来可以重新参考 BerkeleyDB 的模式来实现基于 SequoiaDB 的事务功能。
SequoiaDB for JanusGraph 技术设计
说老实话,当我一开始知道项目是使用一款国产的分布式数据库时,我是拒绝的,我觉得不能够甲方爸爸叫我用什么就用什么,如果它说它很厉害,然后写的软文都是速度快,开发简单,我就非常的不相信。但是当我体验了一下,Duang,这个感觉还真的挺好,确实速度快,开发简单。我还给我很多的朋友推荐,让他们都来试试。
所以说啥,前面自己说啥呢?最后还不是真香!
言归正传,我从 SequoiaDB 的官网上找了一下它的架构图,大家可以看看。
SequoiaDB 采用的是一种叫做“计算和存储分离”的架构,虽然听起来挺神奇的,但是却很好理解,上面的计算层就是一些协议的解析,它支持很多种协议,有 MySQL 的,有 JSON API 的,还有一些对象存储的协议;下面的存储层,看起来就像是一个封装好的盒子,里面可以支持数据的分布式存储。
因为这种计算和存储分离的架构,使得应用的开发者,完全不需要关注底层的数据分布式实现,只要专心做好自己的应用逻辑就好了。
当然,如果你是一名 DBA,那样你还是要学习如何配置 SequoiaDB 底层的分布式存储的。
前面也讲到了,由于 JanusGraph 对底层存储的设计和接口,都是根据列存储来设计的,所以在为 SequoiaDB for JanusGraph 设计时,就需要做出一些调整。
首先是列簇里的 family 设计,我把它拆开来了,将不同的 family 直接对应成 SequoiaDB 的一个 Collection。
最开始时候,我是希望将一条记录的所有列都保存到 SequoiaDB 一个 BSON 里面,但是写到后面,由于 JanusGraph 会依赖 HBase 的列排序功能返回记录,所以这个在 SequoiaDB 里面无法对一条记录的不同列进行排序。所以在最后, JanusGraph 中的一条记录被我拆分成多个 BSON 记录,形式变成了以下的形式。记录以 RowKey 来维护其一条记录的完整性。
{RowKey:"", Key:"", Value:""}
{RowKey:"", Key:"", Value:""}
{RowKey:"", Key:"", Value:""}
{RowKey:"", Key:"", Value:""}
在 BSON 中,RowKey、Key和Value 三个字段的数据类型都是 Binary 格式,这个也是 JanusGraph 自己所独有的解析方法。JanusGraph 保存于 SequoiaDB 中的记录如下面的例子:
{
"_id": {
"$oid": "5e410c444f025855e5552b4c"
},
"Key": {
"$binary": "///////+x38ABZ40DXrgsGMwYTgxZmZiMTc2ODYtY2hlbjE=",
"$type": "0"
},
"RowKey": {
"$binary": "AAAAAAAAAAM=",
"$type": "0"
},
"Value": {
"$binary": "",
"$type": "0"
}
}
02
JanusGraph 代码改造
在前面我向大家介绍 JanusGraph 如何识别不同的存储产品的,所以要增加 SequoiaDB 数据库这个存储选项,首先需要 为StandardStoreManager 类增加 SequoiaDB 的选项,修改的部分如下:
BDB_JE("org.janusgraph.diskstorage.berkeleyje.BerkeleyJEStoreManager", "berkeleyje"),
CASSANDRA_THRIFT("org.janusgraph.diskstorage.cassandra.thrift.CassandraThriftStoreManager", "cassandrathrift"),
CASSANDRA_ASTYANAX("org.janusgraph.diskstorage.cassandra.astyanax.AstyanaxStoreManager", ImmutableList.of("cassandra", "astyanax")),
CASSANDRA_EMBEDDED("org.janusgraph.diskstorage.cassandra.embedded.CassandraEmbeddedStoreManager", "embeddedcassandra"),
CQL("org.janusgraph.diskstorage.cql.CQLStoreManager", "cql"),
HBASE("org.janusgraph.diskstorage.hbase.HBaseStoreManager", "hbase"),
IN_MEMORY("org.janusgraph.diskstorage.keycolumnvalue.inmemory.InMemoryStoreManager", "inmemory"),
SEQUOIADB("org.janusgraph.diskstorage.sequoiadb.SequoiadbStoreManager", "sequoiadb");
StandardStoreManager 类是属于 janusgraph-cord 的模块,所以后续编译后,应该将最新的 janusgraph-core jar 包替换旧的 jar 包。
然后大家只要从 github 上下载 SequoiaDB for JanusGraph 的项目,将其放到 JanusGraph 源码的根目录,修改 maven 的pom.xml 编译脚本,增加 SequoiaDB 的驱动版本说明和添加编译 SequoiaDB for JanusGraph 的项目编译。
<titan.compatible-versions>1.0.0,1.1.0-SNAPSHOT</titan.compatible-versions>
…
<httpcomponents.version>4.4.1</httpcomponents.version>
<hadoop2.version>2.7.7</hadoop2.version>
<hbase1.version>1.4.10</hbase1.version>
<hbase2.version>2.1.5</hbase2.version>
<hbase.server.version>1.4.10</hbase.server.version>
<sequoiadb.version>3.2.1</sequoiadb.version>
...
<modules>
…
<module>janusgraph-doc</module>
<module>janusgraph-solr</module>
<module>janusgraph-examples</module>
<module>janusgraph-sequoiadb</module>
</modules>
对 JanusGraph 重新编译:
mvn -Dlicense.skip=true -DskipTests=true clean install
最后将编译好的 janusgraph-sequoiadb-0.4.0.jar 和 SequoiaDB 的 API 驱动 jar 包保存至 ${JANUSGRAPH_BINARY_HOME}/lib 目录中,就完成了 JanusGraph 扩展 SequoiaDB 存储的操作了。
03
JanusGraph 配置 SequoiaDB 作为存储
大家将 janusgraph-sequoiadb 的模块编译出来的 jar 包和 SequoiaDB 的 JSON API jar 包一起放到 JunasGraph 的 lib 目录里,同时更新 janusgraph-core 的 jar 包后,就完成了 JanusGraph 扩展 SequoiaDB 存储的操作了。
为了让 JanusGraph 能够认识 SequoiaDB 的连接信息,大家还需要准备一个 config 文件。大家在 JunasGraph 的conf 目录里增加一个 janusgraph-sequoiadb.properties的文件,内容大致如下:
gremlin.graph=org.janusgraph.core.JanusGraphFactory
storage.backend=sequoiadb
storage.hostname=10.211.55.7
storage.port=11810
#storage.username=sdbadmin
#storage.password=sdbadmin
storage.meta.visibility = true
cache.db-cache = false
cache.db-cache-clean-wait = 20
cache.db-cache-time = 180000
cache.db-cache-size = 0.5
我给大家介绍几个重要的参数
storage.hostname,SequoiaDB coord 节点的 IP 地址,或者是 hostname
storage.port,SequoiaDB coord 节点的端口号
storage.username,如果 SequoiaDB 配置了鉴权,那样就需要配置鉴权的用户名
storage.password,如果 SequoiaDB 配置了鉴权,那样就需要配置鉴权的密码
当我们已经将 SequoiaDB 的配置信息写到了 config 文件里面了,那么 JanusGraph 对接 SequoiaDB 也是顺利成章的事情。
大家可以直接打开 Gremlin 控制界面,然后就像平时使用 JanusGraph 那样操作即可。
这里,我给大家准备了一下小 demo。
graph = JanusGraphFactory.open('conf/janusgraph-sequoiadb.properties');
graph.addVertex("name", "aaa", "num", 123)
g = graph.traversal()
g.V().values('name')
So easy!
展望未来
现在这个项目还是处于孵化阶段(事实是:一堆的坑,仅仅是 demo 跑通),未来还有很多工作要做,例如:
完善程序,不要那么多的 bug
应该要支持事务功能,毕竟人家 SequoiaDB 支持事务功能呢
对接 JanusGraph 的 Index 模块,也将这块内容让 SequoiaDB 接管
所以啊,未来路还很长,如果有谁看了这篇文章,被我成功感化了,欢迎来找我,也欢迎大家上Git点亮我的小心心,毕竟Star 数量多,会显得我很厉害的样子。
谢谢大家。
项目地址:
https://github.com/ak918808/sequoiadb_for_janusgraph
感谢社区同学的分享,也欢迎大家多多给我们投稿
未来我们也会多和大家分享巨杉数据库社区用户的使用心得体会
敬请期待
【巨杉数据库SequoiaDB】社区分享 | SequoiaDB + JanusGraph 实践的更多相关文章
- 【巨杉数据库SequoiaDB】巨杉Tech | 巨杉数据库数据高性能数据导入迁移实践
SequoiaDB 一款自研金融级分布式数据库产品,支持标准SQL和分布式事务功能.支持复杂索引查询,兼容 MySQL.PGSQL.SparkSQL等SQL访问方式.SequoiaDB 在分布式存储功 ...
- 【巨杉数据库Sequoiadb】巨杉⼯具系列之一 | ⼤对象存储⼯具sdblobtool
近期,巨杉数据库正式推出了完整的SequoiaDB 工具包,作为辅助工具,更好地帮助大家使用和运维管理分布式数据库.为此,巨杉技术社区还将持续推出工具系列文章,帮助大家了解巨杉数据库丰富的工具矩阵. ...
- SequoiaDB 巨杉数据库
传统单点数据库的容量瓶颈,仅仅是分布式数据库所解决的问题之一.更重要的是在未来微服务化应用开发以及云化平台的趋势下,应用不再以“烟囱式”的中间件加数据库模式进行构建,而是采用数千甚至上万的微服务程序构 ...
- 巨杉Tech|SequoiaDB 巨杉数据库高可用容灾测试
数据库的高可用是指最大程度地为用户提供服务,避免服务器宕机等故障带来的服务中断.数据库的高可用性不仅仅体现在数据库能否持续提供服务,而且也体现在能否保证数据的一致性. SequoiaDB 巨杉数据库作 ...
- SequoiaDB巨杉数据库入门:快速搭建流媒体服务器
使用SequoiaDB的分布式文件系统搭建流媒体服务器 介绍 如今使用移动互联网的年轻人开始越来越多使用短视频展示自我,而流媒体则是支撑在线视频播放的核心技术.当我们开始构建流媒体站点时,往往面临最大 ...
- 【操作教程】利用YCSB测试巨杉数据库性能
一.前言 巨杉数据库(SequoiaDB)是国内第一款新一代文档型分布式数据库,巨杉数据库由巨杉软件完全自主研发,拥有完全自主知识产权,不基于任何其它的开源项目.SequoiaDB数据库是为分布式存储 ...
- 巨杉数据库加入CNCF云原生应用计算基金会,共建开源技术生态
近日,巨杉数据库正式加入全球顶级开源社区,云原生应用计算基金会 (Cloud Native Computing Foundation,以下简称CNCF),成为CNCF基金会会员,是中国最早加入的开源云 ...
- 【巨杉答疑】巨杉数据库和mongodb有什么关系吗?
哈罗,艾瑞巴蒂~巨杉答疑栏目今日上线啦! 巨杉数据库作为商业化开源软件,已经拥有大量社区用户.开源至今,大到分布式数据库原理.架构问题,小到SDB巨杉数据库的安装使用问题,大家似乎都有很多问题想要和我 ...
- 【巨杉数据库SequoiaDB】省级农信国产分布式数据库应用实践
本文转载自<金融电子化> 原文链接:https://mp.weixin.qq.com/s/WGG91Rv9QTBHPsNVPG8Z5g 随着移动互联网的迅猛发展,分布式架构在互联网IT技术 ...
随机推荐
- Go语言实现:【剑指offer】平衡二叉树
该题目来源于牛客网<剑指offer>专题. 给定一个二叉树,判断它是否是高度平衡的二叉树. 本题中,一棵高度平衡二叉树定义为: 一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过1. ...
- win10系统安装VMware虚拟机软件以及linux系统
一.安装VMware 1.在VMware官网下载VMware Workstation Pro 15.5.1 下载地址:https://my.vmware.com/cn/web/vmware/detai ...
- 小白学 Python 数据分析(6):Pandas (五)基础操作(2)数据选择
人生苦短,我用 Python 前文传送门: 小白学 Python 数据分析(1):数据分析基础 小白学 Python 数据分析(2):Pandas (一)概述 小白学 Python 数据分析(3):P ...
- TCP加速方式
使用windows scaling TCP Extensions for High Performance, RFC1323,https://www.ietf.org/rfc/rfc1323.txt ...
- mongodb搭建带auth的主从
1:下载mongodb包(mongodb3.4的方法一样,就是mongodb内用户设置到时候不同用户对应不同库,验证时得先创建某个库到用户参考http://ibruce.info/2015/03/03 ...
- Shell脚本 硬盘监控
用shell 写了一个硬盘监控的小程序 #!/bin/bash MAX=95 EMAIL=zonghua@iyunshu.com PART=sda1 IP=`ifconfig |grep -w ...
- iTerm 2 与 oh-my-zsh配合,自定义你的终端。
参考博客:https://www.cnblogs.com/xishuai/p/mac-iterm2.html 参考博客:https://www.cnblogs.com/sasuke6/p/497607 ...
- Flume 自定义拦截器 多行读取日志+截断
前言: Flume百度定义如下: Flume是Cloudera提供的一个高可用的,高可靠的,分布式的海量日志采集.聚合和传输的系统,Flume支持在日志系统中定制各类数据发送方,用于收集数据:同时,F ...
- Spark存储介绍
目录 整体架构 存储相关类 应用启动时 增删改后更新元数据 获取数据存放位置 数据块的删除 RDD存储调用 数据读取 数据写入 cache & checkpoint Reference 记录一 ...
- C# 8.0 新特性之二:接口默认实现
在C#8.0中,针对接口引入了一项新特性,就是可以指定默认实现,方便对已有实现进行扩展,也对面向Android和Swift的Api进行互操作提供了可能性.下面我们来看看该特性的的概念.规 ...