多租户场景
对于SAAS化的产品,通常会有多租户的概念,如果不涉及修改,租户可以共享一份图数据集
如果涉及私有化数据的修改,则不得不做用户的数据隔离。
在hugegraph的应用环境下,我们探索了几个方案
拷贝子图
在一张大图中,事先划分需要做数据隔离的子图。 然后 为每个租户做数据拷贝。
然后再业务层面做区分,对于子图上的数据查询,需要查询拷贝的子集空间。
存在的问题,N个用户,子图中有M 个节点,存储的压力是 N * M,并且计算随着存储的增长也会受到压力。
好处,实现相对简单,自在存储层面做冗余,查询逻辑基本不太变。
增量 patch 存储
每个用户修改的数据量是非常少的,我们可以只把用户的数据做为一个patch 存在另外的地方。
在查询的时候,需要把 master+patch的数据进行merge。
这个方法的存储成本很少,但是需要重写 patch 存储 和 patch merge 逻辑。
在 hugegraph中,我们对patch 存储的处理。
1) 对于每个图数据库,在cassandra中对应一个 patch keyspace,专门存储。
2) patch 的schema 和 master 保持一致。 需要修改 schema api,进行patch+master双写。
3) CRUD api 需要区分数据是放入 patch 还是master还是两者都有
对于patch 查询的处理:
1)需要增加 authentication模块,用户信息写入到全局 threadlocal,以方便查询时使用
2) 在 hugegraph 的vertexStep 和hugegraphStep中,获取全局用户信息,然后根据用户信息去patch库和master库中
查询数据,然后根据操作的类型做一个merge。
这种方式是最灵活的,也是修改最大的,可以支持, 一个大图中,有一部分数据做隔离,如果没有私有数据,就查询master的数据。存储和计算的代价都比较小。
SubGraph Strategy
tinkerpop的标准中,支持对子图策略的划分,利用这个特型,可以通过特定的字段,比如user_id 来做划分。
Traversal.Admin filter= new DefaultTraversal<>();
filter.addStep(new HasStep(filter,new HasContainer("user_id", P.eq("xxx"))));
GraphTraversal<Vertex, Vertex> vertices= g.traversal()
.withStrategies(SubgraphStrategy.build().vertices(
filter).create())
.V().hasLabel("Product")
.bothE("Product_Belong_Industry").otherV().limit(10);
上述的遍历,就是把用户的搜索范围限制在 用户 xxx 的子图中。
这种方式,利用现有特性,支持比较简单。和方案《一》异曲同工。
存在的问题,需要每个用户拷贝数据, 无法做到 master+patch的模式。
网友评论