微服务环境中的MySQL
Daniel Guzmán Burgos 【hudson译】
微服务架构并不是一种新模式,但最近变得非常流行,主要原因有两个:云计算和容器。这一组合解决了每个基础设施的两个主要问题:成本降低和基础设施管理,从而帮助提高了采用率。
然而,所有这些美丽都隐藏着一个黑暗的事实:
微服务最难的部分是数据层
当涉及到像MySQL这样的经典关系数据库时,尤其如此。让我们找出原因。
MySQL和微服务
遵循微服务的两大支柱(云计算和容器),在MySQL范围内可以做什么?云计算和容器为数据表带来了什么?
云计算
云的神奇之处在于,它可以让您轻松地向上/向下扩展实例的大小,从而让您具有成本意识。不再浪费资金在大部分时间未充分利用的大型服务器上。有什么问题吗?它必须很快。快速扩展以准备处理流量,快速缩减以在流量较低时降低成本。
容器
容器的神奇之处在于可以根据资源需求分割硬件。这里的问题是容器传统上用于无状态应用程序。一次性容器。 一般来说,关系数据库,尤其是MySQL,扩展速度不快,而且是有状态的。然而,它可以适应云,并用于微服务的数据层。
缩放立方体

Abott和Fisher的《可伸缩性的艺术》一书描述了一个非常有用的三维可伸缩性模型:Scale Cube。在此模型中,通过在负载平衡器后面运行克隆来扩展应用程序称为X轴扩展。其他两种缩放是Y轴缩放和Z轴缩放。微服务体系结构是Y轴伸缩的应用程序:它定义了一个体系结构,将应用程序构造为一组松散耦合的协作服务。
- X轴:服务和数据的水平复制和克隆(READ REPLICAS)
- Y轴:功能分解和分割– 多租户
- Z轴:沿客户边界的服务和数据分区–(分片)
在微服务上,每个服务都有自己的数据库,以便与其他服务解耦。换句话说:服务的事务只涉及其数据库;数据是私有的,只能通过微服务API访问。
很自然,第一种划分数据的方法是使用多租户模式:

实际上,在尝试多租户之前,可以使用每个服务都有一个表的模型,其中每个服务都拥有一组只能由该服务访问的表,但是因为是“软”划分,跳过API直接访问其他服务的表的诱惑是巨大的。
可以采用每个服务对应一个数据库模式(Schema per service),其中每个服务都有一个专用于该服务的数据库模式,这很有吸引力,因为它使所有权更加清晰。很容易为每个数据库创建一个用户,并使用特定的授权来限制数据库访问。
然而,这种“共享数据库”模式也有一些缺点,如:
- 单一硬件:数据库故障会损害所有微服务
- 与特定数据库相关的资源密集型任务将影响其他数据库(考虑DDL)
- 共享资源:需要共享磁盘延迟、IOPS和带宽,以及CPU、网络带宽等其他资源。
另一种选择是“每个服务的对应一个数据库”

这种策略不共享任何内容。更清晰的逻辑分隔。孤立问题。服务是松散耦合的。事实上,这为微服务打开了大门,使其能够使用最适合其需要的数据库,如图形数据库、面向文档的数据库等。 但与所有事情一样,这也有缺点:
- 最明显的是:成本。要部署的更多实例
- 最关键的:分布式事务。正如我们前面提到的,微服务之间是协作的,这意味着事务跨越多个服务。
最简单的方法是使用两阶段提交实现。但这种解决方案只是对大量锁定问题的公开邀请。它完全无法扩展。那么,有哪些替代方案呢?
- 实现跨服务的事务:Saga模式
- 实现跨服务的查询:API组合或命令查询职责分离(CQRS)
saga是一系列本地交易。每个本地事务都会更新数据库,并发布触发saga中下一个本地事务的消息或事件。如果本地交易因任何原因失败,那么该saga将执行一系列补偿交易,撤销之前交易所做的更改。此处是更多Saga 相关信息。
API组合只是一个组合器,它调用每个微服务上的查询,然后执行结果的内存连接: microservices.io/patterns/da…
CQRS保留一个或多个包含来自多个服务的数据的物化视图。这样就无需对查询大小进行连接:microservices.io/patterns/da…
所有这些备选方案有什么共同点?都是API级别考虑解决方案:实现和维护它成为开发人员的责任。数据层保留的仍然是数据,而不是信息。
让它成为云
有一些方法可以让你的MySQL成为云原生的:容易快速地进行缩放;在容器中运行,许多容器;用Kubernetes编排;拥有Kubernetes的所有优点(健康检查等)。
基于Percona XtraDB集群的 MySQL Percona操作符
Kubernetes操作符是一种特殊类型的控制器,用于简化复杂的部署。运营商提供完整的应用程序生命周期自动化,并利用上面的Kubernetes原语来构建和管理应用程序。