微服务架构下你的数据一致了吗?

标签: dev | 发表时间:2020-12-30 00:00 | 作者:
出处:http://itindex.net/relian

数据一致性问题首先是个业务问题,其次才是个技术问题。在微服务架构下,我们期望每个服务职责单一,这种职责单一体现的是业务价值,如果微服务的拆分过小而导致业务难以实现,那这种拆分是不合理的,业务专家们非常有必要了解系统,从业务侧给出服务拆分的建议。

微服务架构的流行源于它能够带来更快的变化响应能力,比如独立部署,每个服务的能力职责是独立的,可以按需独立发布;再比如每个服务可以由不同的开发团队负责,每个服务的技术栈也可以不同,可以选择更快捷合理的方式实现不同的服务。

然而,微服务架构作为分布式架构,躲不开的一个问题就是数据一致性的问题,特别是在技术异构和数据源类型不同的情况下,传统的分布式事务(2PC或3PC)也很难解决微服务架构下的一致性问题。

数据怎么会不一致呢?

在微服务架构下,多个服务之间通常会定义明确上下游关系,下游系统可以依赖上游系统,下游系统可以通过API查询或修改上游系统的数据;反过来则不然,上游系统不应该知道下游系统的存在,也就是说上游系统不能依赖下游系统,上游系统的变化只能通过异步事件的方式发出,下游系统监听事件并基于事件做对应的数据状态变化。


在基于上面原则的微服务架构下(见上面图示,本文不考虑服务间循环依赖的场景),在上下游服务间的数据通信(图示中的每个箭头表示一种数据通信)一旦发生问题,都会产生数据不一致的场景,下面我们逐一说明:

场景一:下游服务数据状态变化时同步调用上游服务接口失败

举个例子,订单服务是下游服务,库存服务是上游服务,在订单确认时要锁定库存,实现上订单服务在状态变化同时通过同步API修改库存的状态,为了保证数据一致性,在调用库存服务API异常后订单服务会回滚当前的数据状态变更。

在这个场景下,同一个业务流程,需要同时修改两个服务的数据,在以下两种情况下会发生数据不一致的问题:

  • 库存服务API调用成功,库存状态变更,但订单状态变更提交到数据库时失败,结果是库存被锁定,但订单没有确认。
  • 库存服务API调用失败,但实际上库存服务的数据变更已成功,失败原因是响应消息返回订单服务过程中网络异常,订单服务回滚数据变更,结果同样是库存被锁定但没有订单确认。

场景二:上游服务在状态变化时没有发出事件

上游服务每个关键状态变更都可能触发下游服务的一些逻辑链,因此上游服务发布的事件对于下游服务是非常重要的,但这些事件并不影响上游服务自身逻辑,也不影响自身数据状态的变化,因此通常不会设计成阻碍业务流程,那么在事件服务或事件载体(通常是消息队列)与上游服务之间的通信异常,就会导致上游服务的事件发布失败。

这种场景下,上游服务的业务流程已经成功,不可能有再次触发事件的场景,这个事件就丢失了,下游服务因为没有收到上游服务的事件,数据没有做对应的变化而导致数据不一致。

场景三:下游服务没有办法正常消费上游服务的事件

同样,下游服务在消费事件时也很有可能因为一些原因,导致事件的消费失败,这些原因可能包括:

  • 上游服务发布事件的内容格式发生变化
  • 上游服务发布事件的格式没变,但某些字段的可选值空间变化了,比如一些枚举值的扩充
  • 下游服务内部逻辑异常(数据库、跨服务调用等)

上游服务并不关心下游的消费者,所以对于发布出去的事件,上游系统也不关心下游服务是否消费成功,更不会有因某个下游服务消费失败而重发事件的逻辑,这同样会导致类似于场景二的数据不一致。

如何消除数据不一致?

根据CAP理论,分区容错性、可用性和一致性里面必须要牺牲掉一个,而在实际实现过程中,分区容错性和可用性是很难舍弃的,所以通常会舍弃一致性,取而代之会用最终一致性保证数据在可容忍的时长内达到最终一致。

微服务架构也不例外,在服务内部,可以通过本地事务保证数据的强一致性;而当业务发生在多个服务中,我们追求最终一致性。那么怎么解决上面提到的问题,做到跨服务的最终一致性呢?

避免同时跨服务的写操作

这是个业务问题,在微服务的架构下,每个服务都是独立的,如果有一个业务功能需要同时修改两个服务的数据,往往这个业务可以拆分成两个步骤,比如场景一种提到的订单和库存的例子,如果我们可以先锁定库存,然后再确认订单看上去这个问题就迎刃而解了。

因此在业务中发现一个功能需要同时修改两个服务的数据,我们首先可以来讨论这个业务设计是否合理;如果业务上很多场景都要求两个服务的数据保持强一致,那可能我们需要看看微服务的划分是否合理。

最大努力通知 + 最大努力处理

为了解决场景二和场景三的不一致性问题,需要上游服务和下游服务的共同努力:

上游服务需要尽可能将事件发送出去,比如:先同步发送,如果失败改为异步重试,重试多次仍然失败可以先持久化,通过定时任务来重发或者人工干预重发。

下游服务也要尽可能的把事件处理掉,收到事件后可以考虑先将事件持久化,消费成功后标记事件,如果消费失败可以通过定时任务重试消费。

保证幂等性

当我们提到重试,就不得不考虑幂等性的问题,这里的幂等性包括以下两个场景:

  • 上游服务接口的幂等性,保证下游系统的重试逻辑可以得到正确响应
  • 下游服务消费事件保证幂等性,避免因上游多发事件或事件已消费成功后再次重试产生的问题

核心业务数据补偿机制

在分布式系统的执行链路上,每个节点都有可能失败,加上业务的复杂度,即便我们做了很多我们认为万全的准备,数据不一致的情景也很难彻底解决,而对于那些小概率发生但技术解决起来成本昂贵的问题,我们可以尝试通过对业务的深刻理解设计一些后台的维护功能,保证在核心业务数据异常时,可以在一定的规则内进行修复,从而保证业务的顺利进行。

写在最后

数据一致性问题首先是个业务问题,其次才是个技术问题。在微服务架构下,我们期望每个服务职责单一,这种职责单一体现的是业务价值,如果微服务的拆分过小而导致业务难以实现,那这种拆分是不合理的,业务专家们非常有必要了解系统,从业务侧给出服务拆分的建议。

在数据一致性问题上,我们首先要思考业务设计的合理性,其次是当前架构设计的合理性,然后在一定的约束下,通过最终一致性保证业务价值,除非迫不得已,不建议引入分布式事务框架,一方面成本较高,另一方面也会引入性能等新的问题。


更多精彩洞见,请关注微信公众号:ThoughtWorks洞见

相关 [微服务 架构 数据] 推荐:

微服务下的数据架构

- - IT瘾-dev
微服务是一个软件架构模式,对微服务的讨论大多集中在容器或其他技术是否能很好的实施微服务,而本文将从以下几个角度来和大家分享在微服务架构下进行数据设计需要关注的地方,旨在帮助大家在构建微服务架构时,提供一个从数据方面的视角:. 按照 Martin Fowler 的定义,微服务是一个软件架构模式,通过开发一系列的小型服务的方式来实现一个应用.

微服务架构--服务框架,metrics 和调用链数据

- - 行业应用 - ITeye博客
微服务化以后,为了让业务开发人员专注于业. 务逻辑实现,避免冗余和重复劳动,规范研发. 提升效率,必然要将一些公共关注点推到框架. 服务框架 ( 图 9) 主要封装公共关注点. 服务注册、发现、负载均衡和健康检查,. 假定采用进程内 LB 方案,那么服务自注. 册一般统一做在服务器端框架中,健康检.

微服务开发中的数据架构设计

- - ITeye资讯频道
GitChat 作者:陈伟荣. 原文: 微服务开发中的数据架构设计. 关注微信公众号:「GitChat 技术杂谈」 一本正经的讲技术. 微服务是当前非常流行的技术框架,通过服务的小型化、原子化以及分布式架构的弹性伸缩和高可用性,可以实现业务之间的松耦合、业务的灵活调整组合以及系统的高可用性. 为业务创新和业务持续提供了一个良好的基础平台.

微服务架构-数据中台和业务中台(3.27)

- - 人月神话的BLOG
首先我们看下阿里巴巴Aliware团队对企业中台的定义. 即企业中台是由业务中台和数据中台构建起数据闭环的运营体系,实现以数字化资产的形态构建企业核心差异化竞争力. 在原来我谈企业中台的时候,很少专门谈到数据中台和业务中台,更多谈的是技术中台和业务中台,技术中台类似我们原来说的技术平台层和业务不相关.

微服务架构下你的数据一致了吗?

- - IT瘾-dev
数据一致性问题首先是个业务问题,其次才是个技术问题. 在微服务架构下,我们期望每个服务职责单一,这种职责单一体现的是业务价值,如果微服务的拆分过小而导致业务难以实现,那这种拆分是不合理的,业务专家们非常有必要了解系统,从业务侧给出服务拆分的建议. 微服务架构的流行源于它能够带来更快的变化响应能力,比如独立部署,每个服务的能力职责是独立的,可以按需独立发布;再比如每个服务可以由不同的开发团队负责,每个服务的技术栈也可以不同,可以选择更快捷合理的方式实现不同的服务.

谈微服务架构

- - 人月神话的BLOG
其实在前面很多文章谈到SOA,特别是系统内的SOA和组件化的时候已经很多内容和微服务架构思想是相同的,对于微服务架构,既然出现了这个新名称,那就再谈下微服务架构本身的一些特点和特性. 从这个图可以看到微服务架构的第一个重点,即业务系统本身的组件化和服务化,原来开发一个业务系统本身虽然分了组件和模块,但是本质还是紧耦合的,这关键的一个判断标准就是如果要将原有的业务系统按照模块分开部署到不同的进程里面并完成一个完整业务系统是不可能实现的.

微服务与架构师

- - 乱象,印迹
因为工作的关系,最近面试了很多软件架构师,遗憾的是真正能录用的很少. 很多候选人有多年的工作经验,常见的框架也玩得很溜. 然而最擅长的是“用既定的技术方案去解决特定的问题”,如果遇到的问题没有严格对应的现成框架,就比较吃力. 这样的技能水平或许适合某些行业,但很遗憾不符合我们的要求. 软件架构师到底应该做什么,又为什么这么难做好,这都是近来的热门问题,我也一直在和朋友们讨论.

微服务架构下,MySQL 读写分离后,数据库 CPU 飙升卡壳问题解析

- - IT瘾-dev
最近系统(基于SpringCloud+K8s)上线,运维团队早上8点左右在群里反馈,系统登录无反应. 我的第一反应是Mysql数据库扛不住了. 排查问题也是一波三折,有网络问题,也有mysql读写分离后数据库参数优化问题. 1、运维团队早上8点左右在群里反馈,系统登录无反应. 2、DevOps团队通过查看Kibana日志,发现ELK、k8s集群、Redis、Mongodb、Nigix、文件服务器全部报:”Connect Unknown Error“,惊出一身冷汗.

面向服务与微服务架构

- - CSDN博客推荐文章
最近阅读了 Martin Fowler 和 James Lewis 合著的一篇文章  Microservices, 文中主要描述和探讨了最近流行起来的一种服务架构模式——微服务,和我最近几年工作的实践比较相关感觉深受启发. 本文吸收了部分原文观点,结合自身实践经验来探讨下服务架构模式的演化. 面向服务架构 SOA 思想概念的提出已不是什么新鲜事,大概在10年前就有不少相关书籍介绍过.

微服务架构实践感悟

- - mindwind
从去年初开始接触微服务架构的一些理念,然后到今年开始实施系统第四个大版本的架构升级决定采用这套架构理念. 最近关于微服务架构的讨论还是多起来,因为国外一些著名互联网公司(如:Amazon、Netflix 等)从实践中摸索出了一套新的大型系统架构方法论,并取得了成功,树立了很好的示范,然后这套方法论渐渐就被一些技术理论派 人士命名为微服务架构(Microservices).