Cosmos DB已预先公布Gremlin(图谱API)的普遍可用性。可能到2017年底它将不再预览,所以我们可能会认为它足够稳定以便生产。这让我想到以下几点:
我们正在设计一个系统,估计用户数高达1亿用户。每个用户都会在Cosmos中有一些文档来存储与用户相关的数据,这些文档被分区在用户的id(Guid)上。因此,当估计成真时,我们将最终得到至少1亿个分区,每个分区包含一堆文档。
我们不仅会存储与用户相关的数据,还会存储用户之间相互关联的数据(关系)。在论文中,Cosmos应该非常适合这些场景,利用它与文档API交叉api用于普通数据,图形API纯粹用于关系。
其中一种关系的一个例子是Follow。例如,UserX
可以关注UserY
。为了实现这种关系,我们创建了一个Gremlin查询,用于创建Edge
:
g.V().hasId('{userX.Id}').has('pkey','{userX.Partition}')
.addE('follow').to(g.V().hasId('{userY.Id}').has('pkey','{userY.Partition}'))
生成的Edge
会自动分配到UserX
的分区,因为UserX
是外点。
在查询传出边缘(UserX
正在关注的所有用户)时,一切都很好,因为查询仅限于UserX
的分区。
g.V().hasId('{userX.Id}').has('pkey','{userX.Partition}').outE('follow').inV()
然而,当反转查询(找到UserY
的所有关注者),寻找传入边缘时,情况会发生变化 - 据我所知,这将导致完整的跨分区查询:
g.V().hasId('{userY.Id}').has('pkey','{userY.Partition}').inE('follow').outV()
在我看来,一个包含1亿个分区的完整跨分区查询是不可接受的。
我已尝试将Edge
和UserX
放在自己的分区之内,但Graph API不允许我这样做。 (编辑:将Cosmos更改为图谱API )
现在我已经开始实现UserY
和UserX
之间的一对边缘,UserY
的一个传出Edge
和UserX
的传出Edge
对于UserY
,试图让它们保持同步。所有这一切都是为了优化查询的速度,同时也引入了更多的工作来实现最终的一致性。
然后我又想知道Graph API是否真的适合这些场景 - 或者我真的在这里找不到什么东西?
答案 0 :(得分:1)
首先,我将清除您对CosmosDB分区的一些误解。 1亿用户并不意味着1亿个分区。它们只是意味着1亿个分区键。当您创建一个宇宙dB图时,它以10个物理分区开始(这是默认的,可以根据请求更改),然后随着数据的增长自动扩展。
在这种情况下,将有1亿用户分布在10个物理分区中。因此,完整的跨分区查询将命中10个物理分区。另请注意,这些分区将并行命中,因此预期的延迟与命中一个分区类似,除非操作本质上类似于聚合。
答案 1 :(得分:0)
这是经典的分区难题,并非Cosmos / Graph所独有。
如果您的使用模式是很多查询且范围较小,则交叉分区很糟糕。如果返回的是大数据集,那么跨分区的开销对并行性的好处可能微不足道。除非您的查询量持续不断,否则我认为跨分区的开销被夸大了(MS似乎认为每个人都在Cosmos上构建下一个Facebook)。
在OP情况下,您可以针对x跟随y进行优化,或者x跟随y进行优化,或者针对二者进行优化,以使每种方式都有一条边。请注意,RU是按每个分区保留的(即总RU /分区数),因此要有效使用它们,您需要大容量,均匀分布的单个分区查询或跨多个分区的查询。