你的微服务架构需要多种数据模型。你是应该选择混合持久化呢还是多模型数据库?
在过去的十年,大规模的分布式系统呈现爆炸式增长。这一趋势促使在数据库领域产生了一股巨大的创造力,这在软件业的历史上无疑是没有先例的。其结果是诞生了一个健康和充满竞争的数据库市场,我们可以因此在大量的平台中各取所需。但是我们应该如何抉择?
在本文中,我们将探讨如何为根据应用程序去选择核实的数据库模式。(是的,可以有一个以上的选择!),我们也会看看对数据模式的选择可以帮助确定在数据层中将选用哪些技术。
云架构,NoSQL 和微服务架构
随着开发人员开始创建可扩展的Web应用,历史上在数据架构上占主导地位的关系型数据库,开始显示出很大的压力。我们开发了非常流行的社交应用,并开始将越来越多的设备连接到物联网(IoT)。用户大量的读取和写入数据导致了必须扩展数据层,从而出现了新型的数据库来满足这些高可扩展性需求。
在许多情况下,这些新的数据库“NoSQL”或“非关系”的解决方案,所基于的数据模型和传统的关系数据库模型不同。NoSQL数据库包括有文档型、键值对型(key-value)、列式数据库甚至图数据库。通常来说,这些数据库牺牲了一些关系数据库的常见的的特性,如强一致性、ACID事务特性和join连接。
与此同时,和数据库技术的变革一样,在本世纪初的SOA(面向服务的架构),正逐渐演变为微服务架构的体系架构,许多企业也开始逐渐抛弃重量级的SOA体系架构如企业服务总线(ESB),并倾向使用“去中心化”的架构方法。微服务架构的魅力在于其开发、管理和扩展服务都是相对独立的。这给了我们很多在实施方面的灵活性,包括基础架构技术,如数据库。
举个例子,我们假设正在为微服务架构做开发工作,并期待着大规模的可扩展性的需求。无论这个项目是一个新的应用还是对现有应用的重构,我们都有机会针对数据库做出新的选择。
混合持久化(Polyglot persistence)
微服务架构风格的一个关键的好处,是持久性的封装。我们可以根据每个服务的需要,去选择不同的持久化技术。根据每种数据类型的特点而去选择数据存储的方法,被称为混合持久化,这一术语起初是由Martin Fowler等人推广起来的。混合持久化和微服务架构可谓是天作之合。
下图中,展示了一系列的微服务,以及我们如何为每个服务选择不同的数据模式。我不想在本文中,为每种类型的数据库去选择合适的用例。我的意图是要突出各类型数据库的优势,以及为什么混合持久化的方法是值得称道的.
其中,开发服务A的团队,因为该服务是基于大规模数据管理的核心应用,可能使用如Apache Cassandra这样的表格模型数据库。例如,一个零售应用库存应用,可能很适合使用Apache Cassandra。Cassandra提供了一系列协调机制工具,如可调一致,批处理和轻量级的事务机制,可以作为完整ACID事务机制的替代。
服务B支持用众所周知的关键字查找值的方式,例如针对产品目录的描述性数据。对于键值存储模型来说,这是一个很好的例子,在这里,我们通过一个众所周知的键值(如产品ID)查找一系列的数据。很多内存缓存都使用键值对数据模式去支持大规模的快速读取。
服务C可能主要关注半结构化内容,例如Web站点的表单或页面,而文档存储可能非常适合该类型数据。文档存储与键值存储有许多相似之处,但是一个关键的区别是文档型数据支持数据上增加结构,例如对特定属性进行索引以支持快速检索。
服务D可能涉及数据之间的复杂关系导航,例如客户数据和与组织中各部门的客户联系历史数据。这可能涉及其他服务所拥有的数据类型之间的关系。这是一个有趣的案例,因为它开始与上面提到的服务有各自的数据类型的约束相反。在这种情况下,你可以选择为你的服务创建一个具有对底层表的只读访问的图,然后通过这个“前门”处理所有的变化——即通过这个“前门”去调用那些“拥有”这些数据类型的其他服务的API。
***,我们可能还有一个使用关系数据库技术的遗留系统或服务,或者我们有一个服务来管理那些数据量较少,或者不经常变更的数据。关系数据库可能完全适合于这些场景。
单个服务是否应该使用混合持久化?
也有可能的是,我们可以设计一个服务,这个服务需要多种数据库支撑。例如,我们可以创建一个使用键值存储模式作为索引的酒店服务,在酒店名称和ID之间实现映射,而存将关于酒店的描述性数据存储在Cassandra中。
注意,名称映射到ID可以在Cassandra中采用规范化的设计方法去实现,其中一个单独表去维护名称至ID的映射关系。这使用了更多的存储空间,但降低了管理单独键值存储的操作复杂性。
这是我推荐的做法- 针对某个微服务,只要可行,就应该坚持使用单一数据模型(数据库)。如果你发现一种情况,认为单个服务需要两个不同数据库支撑,那么请考虑该服务的粒度是否可能变得太大。你可能需要考虑将该服务拆分为较小的服务。
混合持久化局限性的权衡
混合持久化的主要缺点在于支持多种技术的成本,无论是在最初的开发阶段和将来的运营方面。
主要的开发成本,是在需要培训每个开发人员去掌握每个新的数据库技术。这是非常重要的,尤其是在开发人员频繁流动团队中。
另一个成本是支持多个数据库的操作成本。这会成为一个问题,尤其是当数据库是集中管理,并且团队必须在多种技术的掌握上维持高水平,但这在DevOps环境下,该问题并不会太突出,因为开发团队需要支持他们在生产环境中选择的数据库。
多模型数据库(Multi Model Databases)
作为另外的选择方案或混合持久化模式的补充, 数据库厂商已经开始建立和推广多模型的数据库。术语“模型”指的是数据存储所提供的核心抽象,如表(关系和非关系)、列存储、键值、文档或图。我们可以将一个多模型应用程序看作一个使用多个数据存储类型的应用程序,而多模型数据库是支持多个抽象模型的数据库。
DataStax企业版(DSE)是多模型数据库的典型例子,它核心支持Cassandra的分区行存储(表格)模型,同时也支持基于在其之上的图的抽象层(DSE图)。DSE在核心模型之上构建对应的键值和文档模型也是很简单的,如下图所示。这样,我们可以修改上面的混合持久化的方法,从而利用一个基础数据库引擎为我们所有的服务提供对应的服务,而使用单独的Cassandra keyspaces在不同服务拥有的数据间维护清晰的边界。
下面是它能实现的功能:
[list]
- 表格:我们主要的应用服务A可以通过Cassandra的查询语言(CQL)直接和DSE的数据库打交道。
- 键值对:虽然Apache和Cassandra的分布式版本DataStax都没有提供明确的键值对API,但是象服务B可以通过表设计去支持单个键值和列的方法,去访问
Cassandra,例如:
代码
- CREATE TABLE hotel.hotels (key uuid PRIMARY KEY,value text); // 或者选择blob类型
- 文档型:Cassandra通过使用JSON文件支持文档型风格的数据,这可以用在服务C中。注意因为Cassandra需要针对表定义schema模式,所以不能插入新增任意的JSON列,这是一个可能通常和文档型数据库有关的特性。
- 图:对于象服务D那样相关度很高的数据,DSE的图是一个高度可扩展的图形数据库,它构建于DSE数据库之上。DSE图支持来自Apache tinkerpop项目中强大的功能和表现力的Gremlin API。[/list]
多模型数据库的优点和限制
在考虑是否投资使用多模型数据库(或你已经在使用的数据库的多模型的特性)时,你要考虑我们前文讨论的关于混合持久化中,同样的开发和运营成本的问题。
使用多模型数据库可以让运营变得简单。即使不同的开发团队使用不同的API和不同的交互模式和后端数据库平台打交道,我们也只需要管理一个平台而已,从而提高了效率。
在选择多模型数据库时要考虑的一个问题是如何支持各种模型。一种常见的方法,是基于单一的原生的基础模型的数据库引擎,而其他模型都是构建在其之上。分层数据模型更能展现底层基本模型的特性。
例如,ThoughtWorks技术雷达第16期中,讨论了基于Cassandra构建的DSE图数据库的特性,并且也提到其中需要权衡的内容:
引用
基于Cassandra 构建的DSE图数据库定位是大规模的数据集,相比之下我们长期喜爱的Neo4j开始表现出一定的局限性。这是需要取舍的;比如,你会失去了ACID的事务特性和Neo4j运行时的模式自由的特性,但却可以访问Cassandra的基础表,以及针对分析工作负载和Spark的整合,还有强大的TinkerPop/Gremlin查询语言可以使用,这的确是一个值得考虑的选择。
如果考虑Web应用中的各种数据类型,你可能会发现不同的数据类型对一致性有不同的需求,而且实际需要立即一致性的数据类型数量相对较少。
上面引用的ThoughtWorks的观点中,还提到了在考虑多模型数据库中另一个重要的因素 - 在不同的模型和数据引擎间的整合和交互问题,以及为访问数据的各种操作和分析的用例。DSE支持通过Spark(DSE分析)访问图数据以进行数据分析,并且DSE搜索引擎提供了针对DSE数据库中的数据创建各种查询索引的能力。
微服务数据模型操作的四个步骤
既然我们已经探讨混合持久化和多模型两种方式的优缺点,我们应该如何去决定哪些数据模型适用于大规模可扩展的微服务应用呢?可以按照以下步骤:
- 识别你的应用程序中主要的数据类型,为其中每种类型创建一个服务,并让每个服务掌控相应的持久层。在可能的情况下,为所有服务都使用多模型数据库,允许服务在与数据交互的模型中是不相同的。
- 用Tabular(例如DSE数据库)作为网络水平的可扩展性和可用性的主要模型,然后根据需要在此之上构建分层的键值对和文档数据模型。请务必考虑在操作和分析用例中访问数据的各种方法,以便提前计划如何将搜索索引和复制等特性用于数据分析中心。
- 用图的方法去表示(即DSE图)高度关联的数据,特别是在实体之间的关系有多个或多个属性,并且数量比实体自己的属性多的时候,或者需要在相同的实体之间捕捉多对多的关系的时候。
- 在不需要变更的情况下,保留关系数据库技术中的遗留投资。例如,当你的案例是需要大规模、低延迟和高可用性的时候,那就使用传统的关系型数据库吧。
我希望本文为读者提供了一个有用的框架,来考虑在应用程序中如何和怎么样去支持多数据模型,以及何时考虑使用多模型数据库。