写在前面
声明:本文大部分是基于ArangoDB的论文的翻译,在翻译过程中加入了自己的一些理解和说明。
无论是为一个新的项目或者正在开发的功能模块又或者某一次系统升级去选择技术方案的时候,我们很难做出一个从始至终都非常match的技术方案或者工具,尤其是在为项目选择合适的数据库时,我们更是难以选择,是文档型数据库?K-V数据库?RDMS?还是图数据库? 在软件领域一直存在一种理论:“one size does not always fit all”,但是该理论是否正确,业界的众多专家一直争论不休。该理论建议大型的软件中不同的模块应该采用不同的数据模型进行数据管理。这也就意味着在同一个工程中,你不得不采用多个数据库,但这样做又引入了新的问题:运维和管理的复杂、数据一致性和数据重复的问题等。
机遇与问题总是伴生。这也就是出现原生多模型数据库的原因。本文将会解释什么是多模型数据库,为什么要使用多模型数据库以及多模型数据库应该运用在什么地方。本文将会基于飞机维护保障团队管理的实例,说明如何使用多模型数据库。
什么是多模型数据库
随着多模型数据库与NO-SQL变得越来越流行,很多数据库厂商都标榜自己是“多数据模型”。所以仅仅从市面上现存的多模型数据库产品(有些真的是多模型数据库,有些仅仅将自己炒作成多模型数据库)去总结,很难对多模型数据库有明确的定义,这也导致那些为自己的产品或者项目寻求多模型解决方案的人员对多模型数据库产品的理解不清晰。 对于多模型数据库的理解,最终要的一点就是:我们一定要认识到叠加的多模型方案(例如基于document或者k-v存储之上的Graph层,这其实也算是多模型)与native多模型方案是不同的。
那么什么是原生多模型数据库呢?
简单来说,原生多模型数据库就是将多种数据存储组合在一起。在多模型数据库中,数据可以存储为键/值对,图形或文档,并且可以使用一种声明式查询语言进行访问。也有可能在一次查询中涉及到的数据会跨越多个数据模型。通过native多模型数据库,您可以构建高性能应用程序并且可以很自然的将规模和处理问题的领域范围水平扩展到三种数据模型cover到的所有外延领域。与很多数据库厂商采用的“分层的方法”相比,native多数据模型提供了更大的灵活性和性能优势。简而言之,native多数据模型数据库有一个内核、一种查询语言和多种数据模型。
为什么使用多数据模型
近年来,“多语言持久性”的概念已经变得非常流行。所谓的“多语言持久性”就是在同一个项目或者产品中,同时采用多种不同的数据库。然而,如上所述,一些业界专家对“在大型软件项目中,针对持久层的不同部分采用不同的数据模型”的理论的正确性一直存在极大的争议。按照这种理论的说法,人们应该使用RDBMS存储表结构的数据;使用document存储非结构化的对象数据;使用k/v存储hash表;使用图数据库存储相互之间有复杂引用关系的数据。凡有收益,必有代价。这样所的代价就是:在同一个项目中采用多种数据库,这也就引入了运维的复杂和繁琐(部署更复杂、升级更频繁)、数据一致性问题和数据冗余问题。
这就是多模型数据库需要解决的问题。你可以通过使用多模型数据库(由文档模型、K-V模型和图模型组成的单一数据库引擎)来解决该问题。多模型数据库具有统一的查询语言和API,查询语言和API可以涵盖所有三种数据模型,并且允许在单个查询中混合查询三种模型。选择这三种模型(文档、K-V和图)是因为通过长期的不断尝试,我们发现将这三种模型组合在一起形成的架构可以在任意单一数据模型领域的专门产品(文档型数据、K-V数据库或者图数据库)在查询性能和内存使用率上一较高低。通过使用三种数据模型组合形成的多模型数据库,您可以在不需要使用多种数据库的前提下就可以实现“多语言持久性”。
那么,native多模型数据库的实现机制是什么?在document集合中的每份document都会有一个唯一主键,用来唯一标示一份document。 这样就可以将一份document存储在K/V存储中,当存储在K/V存储中的时候,key是每个document的唯一标示(也就是每个document的唯一主键),通常是字符串,value的内容是json字符串,json字符串其实就是document的实际内容。实际上以json字符串作为value不但没有导致性能下降,还提供了很大的灵活性。图数据模型可以以这样的方式实现:以json的方式来存储vertices和edge的数据。edge被保存在特定的edge集合中,每条edge都必须含有from和to属性,这两个属性分别指向该edge的开始和结束的vertices。
通过上面的的方式实现了三种数据模型的统一。即:通过document的唯一主键作为key,以json形式表示的document的内容作为value,存储在K-V存储中,因此一个K-V对应一个Document;以json形式的document来存储图中的vertices和edge,从而将图数据存储在document中。多模型数据库的层次结构看起来像这样:
我们还需要实现一种通用的查询语言,用户可以通过这种语言不仅完成单独的document、KV和graph的查询,也可以完成跨任意的2个或者3个模型的数据的混合查询。“图查询”是指涉及到对edge的特定连接特性的查询,例如:最短路径、图遍历和模式匹配。多模型数据库中的模式匹配会根据任意查询条件的复杂组合,查询出符合该组合条件的所有路径。这些查询条件包括:单个document或者edge上的某些过滤条件以及整个图上的过滤条件。
native多模型数据库的数据模型
实际案例:飞机维保团队管理
native多模型数据库非常适合于大规模多层级数据的管理,例如:飞机维保团队管理。一个飞机维保团队由几架飞机组成,典型的飞机由数百万个部件组成,而每个大的部件又有很多小的部件组成。我们在脑海中对这些数据大致产生了一个层次关系。为了对团队的数据进行管理,我们必须对不同层次的数据采用不同的存储方式。
每个零件或组件都有名称,序列号,制造商信息,维护间隔,维护日期,分包商信息,手册和文档的链接,联系人,保修和服务合同信息等。每份数据都是其上层数据的一部分。我们可以通过回答下面的问题(包括但不限于),来对数据进行整理和采集:
● 一个组件总共包含哪些部分?
● 对于某一(破损)部件,包含该部件并且被维修过的最小组件是什么?
● 哪些组件需要在下一周进行维修?
飞机维保团队的数据模型
如果我们拥有一个多模型数据库,我们如何对这些飞机维保数据进行建模?
建模方式有多种,但是若想支持快速查询,就应该按照如下方式进行建模:
虽然数据分为不同的层级,但是我们可以对不同层级中的每一项数据都使用JSON格式的document进行存储。由于JSON天生具有灵活性和嵌套性,因此我们可以采用JSON文档存储任意数据。另外由于文档存储是schemaless的,因此即使存储的数据的属性和结构完全不一样,也没有问题,例如你可以使用JSON文档同时存储发动机数据、螺丝钉数据和飞机数据。
除此之外,我们使用图模型来存储不同数据之间的层次和关联关系。具体如下:整个飞机维保团队是一个vertices,每个飞机也是一个vertices,飞机的每个大型组件,如:发动机也是一个vertices。团队vertices与每个飞机vertices之间都有一条edge相连,每个飞机vertices都与飞机的发动机vertices之间也有一条edge,表示发送机是飞机的一部分。每个发动机vertices又会和发动机的子组件对应的vertices之间存在edge。以此类推,直到每个小组件都与它包含的每个单独部分都有edge相连。如下图所示:
我们可以将所有数据放在一个(vertices)集合中,也可以将它们分成不同的集合 - 例如分别对飞机,部件和各个部件进行分类,每类数据一个集合。其实数据存储在一个集合还是多个集合中,对于图来说无关紧要,但是对数据按照分类组合成多个不同的集合,更利于定义和构建二级索引,而二级索引可以使我们的某些特定条件的查询性能更高。
飞机维护记录查询
我们将使用ArangoDB查询语言(AQL)来完成某些特定的查询。现在我们来看下我们可以使用AQL来完成哪些查询。
● 给定一个组件,查看该组件的所有组成部分是什么
要回答该问题,需要从图中的特定vertices(某个给定的组件)开始,首先找到指定的组件,并找到与该“组件”vertices通过edge相连的所有的下层的vertices - 所有vertices都可以通过edge,按照edge的方向遍历到,这是典型的图遍历。
以下是此查询的示例代码,该查询通过图遍历,从查找“components / Engine765”顶点开始,返回可以在4步以内访问到的所有下层vertices:
FOR part IN 1..4 OUTBOUND "components/Engine765" GRAPH "FleetGraph" RETURN part
在ArangoDB中,你可以通过给graph指定一个名称,并且指定哪些document集合包含vertices,哪些document集合包含edge,来定义一个graph。无论document代表的是vertices还是edge,都是通过它的_id属性唯一标识,_id是一个字符串,由集合名称,“/”和主键组成。
上面所示的遍历只需要图形名称“FleetGraph”,起始vertices,以及边的方向:OUTBOUND,这三个条件就可以得到所需要查询的数据,AQL可以支持这种类型的图查询。当然,您可以指定更多的选项, 这里我们不做深入讨论。
●对于某个指定的(孤立的)部件,找到包含该部件并且有维护程序的飞机的最小部件
这种查询涉及从叶子vertices在树中反向向上搜索,直到找到有维护记录的组件vertices。所有数据都可以从相应的JSON文档中读取。由于要经过多少步才能找到符合条件的组件,我们先前是不知道的,因此这是一个典型的图遍历。这种查询相对来说是非常简单的,因为总会有一个唯一的edge从上层的vertices指向下层的vertices。具体的查询过程如下所示:
下面的AQL语句就可以完成该查询:从顶点“parts/Screw56744” :a开始,顺着edge的“inbound”方向的进行查找,直到找到维护属性为true的vertices:component,然后返回找到的顶点:component:
FOR component IN 0..4 INBOUND "parts/Screw56744" GRAPH "FleetGraph" FILTER component.isMaintainable == true
LIMIT 1
RETURN component
从上面的查询语句中,我们指定了graph的名称、起始顶点的_id和目标顶点的过滤规则。由于我们只对第一个顶点感兴趣,因此我们添加了limit 1。我们看到AQL可以直接支持这种查询。
● 飞机的哪些组件在下周需要保养或者维修?
这是一个完全不涉及图的查询:而结果往往与图是正交的。具有正确的二级索引的文档数据模型非常适合此查询。
使用纯粹的图数据库执行这种查询,会比较麻烦,因为我们的查询无法明确的对图结构进行过滤,所以我们不得不求助于二级索引。例如,下次维护日期会存储在组件的某个属性上。为了得到我们想要的答案,我们应该使用document查询,这种查询不会考虑到图的结构和联系。下面的查询语句用于完成这个查询:
FOR c IN components
FILTER c.nextMaintenance <= "2016-12-15" RETURN {id: c._id,
nextMaintenance: c.nextMaintenance}
上面查询语句中看起来像循环的部分是AQL语言用于进行集合迭代的方式。查询优化器能够识别nextMaintenance属性上的二级索引的存在,这样执行引擎不必执行完整的集合扫描来进行filter条件的过滤。可以看到,AQL在RETURN语句中以JSON文档的形式,返回查询到的数据的相关属性内容。
使用多模型查询
为了说明多模型数据库的强大潜力,最后将会演示一个覆盖三种数据模型数据的AQL查询。以下查询首先查找维护到期的组件,为每个到期的组件计算最短路径,然后与contacts集合执行JOIN操作,进而向结果中添加具体的联系信息:
FOR p IN parts
FILTER p.nextMaintenance <= "2016-12-15"
FOR c IN 0..4 INBOUND p GRAPH "FleetGraph"
FILTER c.isMaintainable == true LIMIT 1
FOR person IN contacts
FILTER person._key == c.contact
RETURN {part: p._id, component: c, contact: person}
在查询语句的最后,我们使用到了AQL的join功能。第二个FOR语句会遍历联系人集合。查询优化器会自动通过执行JOIN操作来优化FILTER语句,这种优化措施使得查询非常高效,因为它可以利用联系人集合的主索引进行快速哈希查找。
这是一个涉及多个数据模型查询的典型示例。本次查询会涉及到三种数据模型:具有二级索引的文档,图查询以及由快速键/值查找提供支持的JOIN。想象一下,如果三个数据模型没有在同一个数据库引擎中,或者如果无法在同一个查询中混用这三种数模型,我们就必须采用三种数据库引擎,并且需要通过应用程序对从不同数据引擎中查询出来的数据进行加工、聚合和处理。
更重要的是,本示例表明,多模型数据库确实可以极大地提升应用程序的查询的性能。在没有图数据库的情况下,要根据路径长度进行图查询(查询的路径及步骤并不是预知的),只能转变为繁琐的、低效的join查询。但是,纯图数据库又不能通过二级索引来提高查询的性能。我们可以将键/值查找与图查找进行Join,来提供多模型数据库的灵活性。例如,在上述情况下,我们不必将整个联系信息嵌入到每个路径中,只在最后一个查询中执行JOIN操作即可。
数据建模经验
● JSON对于非结构化和结构化数据都非常通用 JSON的递归特性允许嵌入子文档和可变长度列表。您甚至可以将表的行存储为JSON文档。现代数据存储非常擅长压缩数据,与关系数据库相比,没有内存开销。对于结构化数据,可以使用可扩展的HTTP API根据需要实现schema验证。
● 图适用于关系建模 在很多实例中,图可以最自然的反应实际的数据模型,而不需要进行反模式处理。图不仅可以存储关系数据,还可以存储vertices和edge的标签信息。JSON天生就非常适合存储这些vertices和关系数据。
●图数据库特别适用于图查询
通过图数据库可以非常容易的实现“最短路径”和“图形遍历”。而这些的基本功能中涉及到的对某个vertices的outgoing和incoming的边的反复频繁遍历,均由图数据库为你实现,你使用的只是这些基本功能的接口,而不需要关注底层实现细节。
●多模型数据库可以与专业解决方案相媲美 我们可以将多种数据模型组合在一个数据库引擎中。这种组合不是妥协,它可以作为文档存储,K-V存储,也可以作为图数据库。并且可以与专业的解决方案一样高效。
●多模型数据库可以同时提供多种数据模型,而不需要引入过多的运维和研发成本 多模型数据库引擎可以极大地降低同时使用多种数据库模型的复杂性。虽然是多数据模型,但是你也可以将多个数据模型中的数据都存储在一个数据库存储引擎中。在单个查询中混合使用不同的数据模型,可以极大的提升应用程序和设计的性能。即使您选择将多模型数据库部署成多个数据库实例,但是你仍然只需要部署一种技术(只需要学习一种数据库产品即可)。
●多数据模型可以解决的问题领域更加广泛 由于多模型数据库优点包括:支持丰富的查询语句、数据建模更加灵活以及各个模型之间相对独立的持久化特性等,多模型数据库与各单一领域的传统数据库相比可以解决的问题领域更加广泛。
多模型数据库的适用场景
内容管理
文本内容是schema less的,这种数据更适合适用document来存储。但是在不同的内容数据之间往往存在着各种联系,这些联系又可以由图来进行最自然的表现。
用户定义的复杂数据结构
任何处理用户定义的复杂数据结构的程序都可以从document存储的灵活性中受益,并且可以通过图对这些复杂的数据结构和关系进行管理。
电子商务系统
电子商务系统,比如京东,需要存储客户和产品数据(JSON),购物车数据(键/值),订单和销售(JSON或图)数据以及推荐数据(图),这些不同的数据都需要不同的数据模型进行存储,但是又需要针对所有这些数据执行大量的join查询,因此使用多模型数据库是最合适不过的了。
企业组织架构管理
企业组织结构的自然表现就是图,而基于组织架构的权限管理又需要图形和文档的混合使用。
欺诈检测
在这种场景中,通常需要存储大量的日志数据,这些数据涉及到帐户,IP地址,机器等不同的类型。这可以通过图进行数据建模。检测欺诈会使用到图数据库中复杂的模式匹配(例如,与单个主机或帐户建立的异常连接数),但有时也会同时使用二级索引与图数据进行join查询,从而获得所需要的数据。
身份与权限管理
与上述的企业组织结构管理一样,身份和权限管理通常涉及到具有层次结构的数据,并且通常层次结构中较高层的人或者实体除了具有其下属所拥有的所有权限之外,还存在一些特权。这种数据最好用树或有向无环图来描述。在判断有没有权限的时候,通常会涉及到对图数据的检索和分析,但是在进行身份认证的时候,只是进行身份数据的核对和查询,这个过程是不会涉及到图数据的检索和处理的。
物联网
IoT(internet of things)物联网产生大量的状态数据,地理位置信息,传感器数据等。物联网中的实物都是分层次的。例如,同一房屋中的所有家庭设备都属于房屋,而房屋又属于更高层级的物体。这意味着物联网中有关设备的数据可以很自然地由图建模,并且大量的传感器数据具有不同的结构,而且经常需要进行关联查询。
知识图谱
知识图谱是大量数据的集合,知识图谱系统中的大多数查询仅使用图数据模型,但通常也只需要对图数据中的vertices进行常规过滤查询。
物流系统
在物流系统中,会产生大量的数据:地理位置信息,任务,任务依赖关系,任务所需的资源等。这些数据的结构多种多样,相互之间的关联性很强。因此对这些数据的查询包括:针对依赖关系的图形查询和忽略依赖关系的基于标准索引的传统查询。
基础设施运维和管理
计算机网络及相关联的计算机主机一起构成一张图,因此对这些基础设施的管理会频繁的对这张图进行查询和操作。包括:基于关联关系的图操作,以及对单一vertices的查询和设置。
实时推荐引擎
电子商务系统中实时推荐引擎会为客户提供合理有效的实时购买建议,这实质上是对图数据库中的路径进行模式匹配查询,比如系统希望向客户A推荐已经被另一个与客户A存在某种联系的客户B已经购买的东西。不仅如此,推荐系统还会使用产品目录上的二级索引进行查询,例如将产品类目的销售排名以及销售数据考虑进行综合查询。
社交网络
社交网络是大规模高度关联的图数据的主要使用场景,在社交网络中典型查询就是图查询,但是,实际应用程序还需要其他的常规查询,因此也需要二级索引,并且可能需要根据连接键进行join查询。
交通管理系统
街道网络可以非常自然地被建模为图。交通流量数据产生大量基于时间的数据,这与街道网络密切相关。想要做出有关交通管理的优秀决策,涉及到对所有这些数据的聚合,图遍历和join查询,并使用算法进行建模和计算。
版本管理系统
版本管理系统典型的案例就是github。系统通常使用有向无环图进行数据存储,查询涉及到:图查询和其他查询。
工作流管理系统
工作流管理系统通常使用图来模拟任务之间的依赖关系,管理系统需要同时涉及到图查询和常规检索查询。
结语
时代在发展、技术在进步。我相信现有的技术终将成为历史,目前多模型数据库引擎处于起步阶段,我们站在技术革新的十字路口,需要看清方向,不断尝试新的技术,才能在未来享受自己的正确技术选择带来的红利。京东商城tig团队在浪潮之巅,我们认定多模型数据库将会下一代数据库技术的新的趋势,因此我们抓住机会,迎难而上,并自主研发多模型数据库引擎ChuBaoDB,我们相信多模型数据库引擎方向的正确性,并付诸实践实现它。请对ChuBaoDB拭目以待。
参考
吕信原创,转载请注明出处,尊重知识,尊重别人的劳动