分布式事务不理解?一次给你讲清楚!

来源:juejin.im/post/5baa54e1f265da0ac2566fb2

整编:Java技术栈(公众号ID:javastack)

文章纲要

此次分享的缘由

目前分布式事务问题是怎么解决的

行业中有什么解决方案

这些解决方案分别有什么优缺点

别人是怎么做的

我们可以怎么来做

此次分享的缘由

支付重构

考虑支付重构的时候,自然想到原本属于一个本地事务中的处理,现在要跨应用了要怎么处理。拿充值订单举个栗子吧,假设:原本订单模块和账户模块是放在一起的,现在需要做服务拆分,拆分成订单服务,账户服务。原本收到充值回调后,可以将修改订单状态和增加金币放在一个mysql事务中完成的,但是呢,因为服务拆分了,就面临着需要协调2个服务才能完成这个事务

所以就带出来,我们今天要分享和讨论的话题是:怎么解决分布式场景下数据一致性问题,暂且用分布式事务来定义吧。

同样的问题还存在于其他的场景:

送礼:

调用支付服务:先扣送礼用户的金币,然后给主播加相应的荔枝

确认第一步成功后,播放特效,发聊天室送礼评论等复制代码

充值成功消息:

完成充值订单

发送订单完成的kafka消息

在涉及支付交易等付费接口的时候,数据一致性的问题就显得尤为重要,因为都是钱啊

目前分布式事务是怎么解决的呢?

问题肯定不是新问题,也就是目前已经有相应的解决方案了,那就看一下现在是怎么来解决这类问题的吧。

购买基础商品成功发送支付订单完成消息为例:

假设支付下单购买基础商品,此刻已经收到支付回调,订单已经处理成功了,这个时候kafka服务故障,消息发送失败;而这个时候处理订单的事务已经提交了,怎么保证订单完成的消息一定能发出去呢?

解读一下这个流程:

绿色部分,表示流程正常运行的交互过程:

先往JobController中提交一个job(用于故障恢复)

提交成功后,开始处理订单逻辑

处理完订单逻辑之后,开始发送kafka消息

消息也发送成功后,删除第一步提交的job

黄色部分,表示流程出现了异常,数据可能存在不一致现象。这个时候就需要进行流程恢复

JobController任务控制器定时去redis查询延时任务列表(每个任务都有一个时间戳,按时间戳排序过滤)

将任务进行恢复(调用job注册时定义的处理方法)

任务执行成功,表示流程完成;否则下一个定时周期重试

问题:

基于redis存储恢复任务,可能存在数据丢失风险

架构体系中没有统一的分布式事务规范,可否将这层逻辑独立为分布式事务中间件

缺少事务执行策略管理,如:控制最大重试次数等

事务执行状态没有记录,追查需要去翻看日志

行业中有什么解决方案

说解决方案之前,我们先了解一下这些方案的理论依据,有助于帮助我们来理解和实践这些方案

理论依据(讨论的前提)

本地事务、分布式事务

如果说本地事务是解决单个数据源上的数据操作的一致性问题的话,那么分布式事务则是为了解决跨越多个数据源上数据操作的一致性问题。

强一致性、弱一致性、最终一致性

从客户端角度,多进程并发访问时,更新过的数据在不同进程如何获取的不同策略,决定了不同的一致性。对于关系型数据库,要求更新过的数据能被后续的访问都能看到,这是强一致性。如果能容忍后续的部分或者全部访问不到,则是弱一致性。如果经过一段时间后要求能访问到更新后的数据,则是最终一致性

服务端角度,如何尽快将更新后的数据分布到整个系统,降低达到最终一致性的时间窗口,是提高系统的可用度和用户体验非常重要的方面。对于分布式数据系统:

N — 数据复制的份数

W — 更新数据时需要保证写完成的节点数

R — 读取数据的时候需要读取的节点数

如果W+R>N,写的节点和读的节点重叠,则是强一致性。例如对于典型的一主一备同步复制的关系型数据库,N=2,W=2,R=1,则不管读的是主库还是备库的数据,都是一致的。

如果W+R

需要明确的一点是,对于一个分布式系统而言,分区容错性是一个最基本的要求。因为 既然是一个分布式系统,那么分布式系统中的组件必然需要被部署到不同的节点,否则也就无所谓分布式系统了,因此必然出现子网络。而对于分布式系统而言,网 络问题又是一个必定会出现的异常情况,因此分区容错性也就成为了一个分布式系统必然需要面对和解决的问题。因此系统架构师往往需要把精力花在如何根据业务 特点在C(一致性)和A(可用性)之间寻求平衡。

BASE 理论

BASE是Basically Available(基本可用)、Soft state(软状态)和Eventually consistent(最终一致性)三个短语的缩写。BASE理论是对CAP中一致性和可用性权衡的结果,其来源于对大规模互联网系统分布式实践的总结, 是基于CAP定理逐步演化而来的。BASE理论的核心思想是:即使无法做到强一致性,但每个应用都可以根据自身业务特点,采用适当的方式来使系统达到最终一致性。

BASE理论面向的是大型高可用可扩展的分布式系统,和传统的事物ACID特性是相反的,它完全不同于ACID的强一致性模型,而是通过牺牲强一致性来获得可用性,并允许数据在一段时间内是不一致的,但最终达到一致状态。但同时,在实际的分布式场景中,不同业务单元和组件对数据一致性的要求是不同的,因此在具体的分布式系统架构设计过程中,ACID特性和BASE理论往往又会结合在一起。

柔性事务

不同于ACID的刚性事务,在分布式场景下基于BASE理论,就出现了柔性事务的概念。要想通过柔性事务来达到最终的一致性,就需要依赖于一些特性,这些特性在具体的方案中不一定都要满足,因为不同的方案要求不一样;但是都不满足的话,是不可能做柔性事务的。

可见性(对外可查询)

在分布式事务执行过程中,如果某一个步骤执行出错,就需要明确的知道其他几个操作的处理情况,这就需要其他的服务都能够提供查询接口,保证可以通过查询来判断操作的处理情况。

为了保证操作的可查询,需要对于每一个服务的每一次调用都有一个全局唯一的标识,可以是业务单据号(如订单号)、也可以是系统分配的操作流水号(如支付记录流水号)。除此之外,操作的时间信息也要有完整的记录。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20181207A08P0V00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

扫码关注云+社区

领取腾讯云代金券