titan0.1源码研究(1)

简介: 为什么是titan0.1?因为代码量小,后面的代码都是从0.1发展来的,代码量是增加了,但是代码结构基本没变。titan-0.1有3万多行代码,而且还没有弄成maven的多模块。用来学习正好。等熟悉了再跟后面的版本比对,看看哪些地方更新了。

为什么是titan0.1?因为代码量小,后面的代码都是从0.1发展来的,代码量是增加了,但是代码结构基本没变。
titan-0.1有3万多行代码,而且还没有弄成maven的多模块。用来学习正好。等熟悉了再跟后面的版本比对,看看哪些地方更新了。

titan是一个图数据库,没有自己的存储后端,需要安装hbase,cassandra等数据库。我们使用cassandra。
下载cassandra-1.1.3.tar.gz。解压后,配置一个Cassandra_HOME环境变量,然后启动它:

cd $CASSANDRA_HOME\bin
cassandra 

先来看一个小demo吧,稍微熟悉一下titan。
注意titan0.1要想遍历结点的话,必须要建索引:
把源码test模块下的TitanTestBed修改成这样:

Configuration conf = new BaseConfiguration();
conf.setProperty("storage.backend","cassandra");
conf.setProperty("storage.hostname","127.0.0.1");
TitanGraph g = TitanFactory.open(conf);
// 给titan的vertex的name2属性建一个索引。
g.createKeyIndex("name2", Vertex.class);
// 新建一个结点,手动给结点的id赋值
Vertex v = g.addVertex(1);
v.setProperty("name2", "zhangsan");
// 如果上面没有建索引,这句会报错:java.lang.UnsupportedOperationException: The configured storage backend does not support global graph operations - use Faunus instead
// 参考这里: https://groups.google.com/forum/#!topic/aureliusgraphs/jU6-Yyxm9F4
System.out.println(g.getVertices("name2", "zhangsan").iterator().next().getId());
System.out.println(g.getVertex(1).getProperty("name"));
g.stopTransaction(Conclusion.SUCCESS);
g.shutdown();

好,正式开始。代码太多了,从哪儿下手呢?
一看readme.md文件。哦,内容比较少,没有什么干货。
二看包名,有5个大包:core, diskstorage, graphdb, tinkerpop, util。先看core包。
三看接口。core包里一共有15个接口。在eclipse选择类名,按F4会显示这个接口的继承关系及接口里的方法。

titan遵守tinkerpop规范,所以,必定会实现blueprints(新版本叫gremlin structure)里的接口。
在实现blueprints的接口之前,titan自己定义了一些接口。这些接口继承了blueprints的接口。
这样有一个好处,以后扩展的时候只需要修改自己的接口就行了,blueprints里的不用动。

core包的15个接口:
core15_

我们知道图有两个要素,结点和边。
titan是这样抽象的:

最顶层的接口叫TitanElement
TitanElement_

这是所有元素都需要用到的方法。

然后InternalElement和TitanVertex两个接口继承了TitanElement。
InternalElement接口里只有一个方法setID。似乎这个接口并没有什么用。 这个暂时不用管,以后我们再好好研究一下它。因为源码里凡是以Internal开头的接口,代码里都没有注释,所以先不管它。

TitanVertex很明显是操作vertex用到的接口。于是乎我们猜测,代码里一定会有一个操作边的接口叫TitanEdge。
不好意思猜错了。没有一个接口叫TitanEdge的,只有一个TitanRelation。

为什么要这样安排?来看一下TitanVertex的继承关系。
TitanVertex_

因为vertex和edge的属性都有键(key),vertex和edge本身都有标签(label)。所以将key和label抽象成TitanType,这样以后不管是结点还是边,都可以用这个父类接口了。

因为vertex不仅有属性(property),同时还有边的信息。将属性和边抽象成TitanRelation。这样以后不管是addProperty还是addEdge,都可以用这个父类接口了。

因为都跟vertex有关。所以TitanType和TitanRelation继承了TitanVertex。虽然乍一看有点怪,不过非常合理。

blueprints的Vertex接口里只有3个方法getEdges,getVertices,query。
TitanVertex:继承了blueprints的Vertex接口。
但是显然方法还是太少了,所以TitanVertex里又添加了许多方法,见上图。

这些方法就够了吗?当然不够。
TitanRelation里增加了getDirection, getType, isDirected, isEdge, isIncidentOn, isLoop, isModifiable, isProperty, isSimple, isUndirected, isUnidirected(对跟左边的方法就一字之差)
TitanEdge里增加了 getOtherVertex, getTitanLabel, getVertex 3个方法。
TitanProperty里增加了getAttribute, getPropertyKey, getVertex 3个方法。

TitanType里增加了getGroup, getName, isEdgeLabel, isFunctional, isModifiable, isPropertyKey, isSimple
TitanKey里增加了 getDataType, hasIndex, isUnique 3个方法。
TitanLabel增加了 isDirected, isUndirected, isUnidirected 3个方法。

不要觉得烦,这就是软件设计里的接口隔离原则。弄成一个个小的接口,一点一点的增加方法。

以Titan开头的8个接口就定出了titan基本元素的框架。core包里还有7个接口,分别是:
AttributeSerializer,DefaultTypeMaker,TitanGraph,TitanQuery,TitanTransaction,TypeMaker,VertexList

TitanQuery:毫无疑问,继承了blueprints的Query接口。blueprints Query接口只有9个方法。
count, direction, edges, has, interval, labels, limit, vertexIds, vertices。
TitanQuery增加了很多方法:
clone, count, directon, edges, group, has, inMemory, interval, keys, labels, limit, onlyModifiable, properties, propertyCount, relations, titanEdges, types, vertexIds.
这里虽然有些方法在父类接口里已经有了,不过没关系。 java接口里的方法都是抽象的。实现类只要实现了抽象方法就行。反正方法签名都是一样的,虽然父类接口和子类接口都有声明,编译器只会加载一次,所以不会有问题。

TitanTransaction:继承了blueprints的TransactionalGraph和KeyIndexableGraph两个接口。
TransactionalGraph接口里只有 shutdown, stopTransaction 2个方法。
KeyIndexableGraph 接口里只有 createKeyIndex, dropKeyIndex, getIndexedKeys 3个方法。
TitanTransaction 增加了很多方法:
abort, addEdge, addProperty, addVertex, commit, containsType, containsVertex, getEdgeLabel, getPropertyKey
getType, getVertex, getVertices, hasModifications, isClosed, isOpen, makeType, query

咦很多方法前面出现过了对不对? 比如addProperty, addEdge, getVertices。 是的,这些方法有一个要求,都要传入vertex对象,所以最后调用的还是vertex的方法,而不会是tx的。

VertexList:继承了java里的Iterable接口,遍历的时候要用到这个接口。有5个方法: get, getID, getIDs, size, sort
AttributeSerializer:为attribute的值序列化用的,允许用户自定义序列化器。只有read, writeObjectData两个方法。

TypeMaker:TitanType的工厂。TitanType可以被配置用来提高数据校验,更好的存储效率和更高的性能。 TitanType给某个类型所有的TitanRelation定义schema。
有这些方法: dataType, directed, functional, group, indexed, makeEdgeLabel, makePropertyKey, name, primaryKey, signature, simple,
undirected, unidirected, unique
用户可以用com.thinkaurelius.titan.core.TitanTransaction#makeType()自定义一个类型。

DefaultTypeMaker:当graph被配置成 边label和属性的key第一次被使用时自动创建边label和属性的key。分别使用DefaultTypeMaker实现类的makeLabel(String, TypeMaker)
或者makeKey(String, TypeMaker)来定义他们。 也可以自定义一个DefaultTypeMaker的实现类,该类指明了默认情况下这些类型是如何被定义的。
在配置里使用全路径指明实现类。

TitanGraph:继承了blueprints的Graph, KeyIndexableGraph, ThreadedTransactionalGraph 3个接口。 哦,人家blueprints也是接口隔离的。
Graph:addEdge, addVertex, getEdge, getEdges, getFeatures, getVertex, getVertices, removeEdge, removeVertex, shutdown。

KeyIndexableGraph:createKeyIndex, dropKeyIndex, getIndexedKeys

ThreadedTransactionalGraph: startTransaction

嗯,TitanGraph把vertex, edge, tx, serializer都封装起来了。我们大概知道titan要做哪些事了:

打开数据库,开启事务,构造vertex和edge,将数据序列化一下,然后将序列化后的数据提交到存储后端(hbase, cassandra等)。

这里最难的是事务。titan没有自己的存储后端,它是一个图数据层。
BigTable是很好,可惜就是没有原生地提供事务支持,所以titan自己实现了一个分布式事务。

本次收获:面向接口编程,接口隔离,接口继承。

titan源码有太多太多值得我们学习的地方:
设计模式,线程安全,maven多模块,maven各种插件的使用,单元测试,持续集成等。把这个项目研究好了,Java水平一定会有质的提升。

目录
相关文章
|
26天前
|
机器学习/深度学习 并行计算 计算机视觉
CUDA:王者之巅——探究CUDA为何能成为并行计算的佼佼者
本文探讨了CUDA在并行计算领域的崛起及其成为佼佼者的原因,详细介绍了CUDA的技术背景、架构原理及在深度学习、图像处理等领域的应用案例,展示了其显著的性能优势与优化方法,并展望了CUDA在未来计算技术发展中的潜力与方向。
|
2月前
【PCB设计秘籍】AutoDesk Eagle轻松驾驭:LMC555CN/NOPB器件库下载与添加全攻略,设计效率飙升!
【8月更文挑战第2天】【PCB设计】AutoDesk Eagle如何下载和添加LMC555CN或LMC555CN/NOPB器件的库
42 11
|
2月前
|
开发者 前端开发 Apache
【绝不错过!】揭秘Wicket大神级插件,带你飞越编程极限,探索Web应用开发新大陆!
【8月更文挑战第31天】Apache Wicket是一个成熟的Java Web框架,以其组件化体系结构、直观的API及对MVC的支持著称。其活跃社区贡献了大量插件和扩展,显著提升了Wicket的功能性。本文推荐几个实用插件,如**Wicket Ajax Support**,可轻松添加Ajax功能,提升用户体验;**Bootstrap for Wicket**则将Bootstrap与Wicket结合,美化应用界面。
29 0
|
2月前
|
开发者 缓存 数据库
【性能奇迹】Wicket应用的极速重生:揭秘那些让开发者心跳加速的调优秘技!
【8月更文挑战第31天】在软件开发中,性能优化是确保应用快速响应和高效运行的关键。本书《性能调优:Apache Wicket应用的速度提升秘籍》详细介绍了如何优化Apache Wicket应用,包括代码优化、资源管理、数据库查询优化、缓存策略及服务器配置等方面。通过减少不必要的组件渲染、优化SQL查询、使用缓存和调整服务器设置等方法,本书帮助开发者显著提升Wicket应用的性能,确保其在高并发和数据密集型场景下的稳定性和响应速度。
36 0
|
机器学习/深度学习 缓存 分布式计算
Transformer取代者登场!微软、清华刚推出RetNet:成本低、速度快、性能强
Transformer取代者登场!微软、清华刚推出RetNet:成本低、速度快、性能强
114 0
Transformer取代者登场!微软、清华刚推出RetNet:成本低、速度快、性能强
|
机器学习/深度学习 编解码 缓存
全面碾压AdamW!谷歌新出优化器内存小、效率高,网友:训练GPT 2果然快
全面碾压AdamW!谷歌新出优化器内存小、效率高,网友:训练GPT 2果然快
410 0
|
机器学习/深度学习 人工智能 自然语言处理
VLDB 2023 | 北大河图发布分布式训练神器Galvatron, 一键实现大模型高效自动并行(2)
VLDB 2023 | 北大河图发布分布式训练神器Galvatron, 一键实现大模型高效自动并行
274 0
|
存储 人工智能 自然语言处理
VLDB 2023 | 北大河图发布分布式训练神器Galvatron, 一键实现大模型高效自动并行(1)
VLDB 2023 | 北大河图发布分布式训练神器Galvatron, 一键实现大模型高效自动并行
206 0
|
机器学习/深度学习 人工智能 测试技术
神经引擎这回行了吗?iPhone 14 Core ML性能测评已出
神经引擎这回行了吗?iPhone 14 Core ML性能测评已出
169 0
|
人工智能 并行计算 架构师
CUDA编程模型都改了!英伟达架构师团队撰文详解:Hopper为啥这么牛?
CUDA编程模型都改了!英伟达架构师团队撰文详解:Hopper为啥这么牛?
323 0