分布式常见解决方案

一、分布式锁解决方案

redis实现分布式锁

实现逻辑:
1.加锁 setnx
1)为了避免死锁问题,setnx完之后需要expire设置TTL失效时间
2)为了避免TTL失效的时候业务还未完成导致多个应用抢到锁,可以使用守护线程不断地延长TTL;
3) 复合命令实现加锁。 set key value ex 10 nx
2. 解锁del
1) 使用lua脚本实现原子性操作:在del之前判断是否是持有锁的线程,需要存在唯一标识

zookeeper实现分布式锁

1.连接ZK、创建分布式锁的根节点/lock
2.获取锁时,在/lock下面创建一个临时顺序节点;
3. 获取根节点下所有子节点,然后判断当前节点是否为最小节点,如果是,则获取到锁,否则监听当前节点的前一个节点;
5. 释放锁时,删除临时节点,然后删除当前节点。

二、分布式ID解决方案

1.数据库自增ID(段号、批量处理)

2. UUID

概念:UUID是通用唯一标识码的缩写,集群全局唯一不会重复,UUID是基于当前时间、计数器、机器mac地址等数据生成;
优点:本地生成、没有网络IO、性能好、全局唯一且不重复、使用简单无需引入中间件;
缺点:空间占用比较多(16个字符)、千万级别或亿级别特别浪费空间、不是递增且无序、随机写入索引性能下降;
场景:对表空间没太多限制、重构类系统、UUID不作为查询字段的非高并发系统、集群部署的中间件唯一ID;

3.雪花算法

概念:twitter开源的分布式ID生成算法,主要是由64位的long型生成的全局ID、引入了时间戳和ID保持自增的的属性。组成结构如下:
1. 时间戳:41位,从2015-01-01 00:00:00开始,到当前时间戳,共41位;
2. 数据中心ID:5位,最多支持32个数据中心;
3. 机器ID:5位,最多支持32个机器;
4. 序列号:12位,支持每毫秒产生4096
5. 随机数:1位,用于解决时钟回拨问题;
优点:不依赖外部组件、性能号、按时间递增;
缺点:数据中心+机器的设置不合理高并发会导致重复
场景:互联网高并发系统

4.Redis自增ID (key的incr)

概念:Redis计数器,原子性自增,调用incr、incrBy方法
优点:并发性能高、有顺序、生成ID格式自定义
缺点:使用场景有限、自增所以数据量容易被猜到、不安全、引入了中间件、redis集群部署需要保证高可用成本高;
场景:生成ID需要自增、高性能、适合运营管理后台唯一ID的生成,如活动编号;

三、分布式事务

1. 分布式事务基础理论

1.1 CAP理论

CAP理论:

  • 满足一致性(Consistency):写操作后可以读取到最新的数据,当数据分布在多个节点时,从任意节点都可以读到最新的状态
  • 满足可用性(Availability):任何事务操作都可以得到响应结果,且不会出现响应超时或响应错误。(有可能读到旧数据)
  • 满足分区容错性(Partition tolerance):在网络分区的情况下,系统仍然保持可用性,仍可对外提供服务。

组合方式: 在所有的分布式事务中不会同时具备CAP三个特性,因为具备了P的前提下,CA是矛盾的;

  • AP:放弃一致性,保证可用性和分区容错性(大部分分布式系统的选择);这个时候用户在一段时间内会读到旧数据;
  • CP:放弃可用性,保证一致性和分区容错性;zookeeper的强一致性就是,此外银行转账也是需要等双方银行系统都完成整个事务才可以;
  • CA:放弃分区容错性,保证一致性和可用性;系统将不再是一个标准的分布式系统;

1.2 BASE理论

BASE理论:

  • Basically Available 基本可用,允许损失部分可用功能,保证核心功能可用。如电商网站交易付款出现问题,商品依然可以正常浏览
  • Soft State 软状态,由于不要求强一致性,所以系统存在中间状态即软状态。这个状态不影响系统可用性,如订单的支付中、数据同步中等。
  • Eventual Consistency 最终一致性,经过一段时间后,所有的数据节点都将会达到一致状态,但是需要一段时间的延迟。如支付中会变成支付成功、支付失败;

2. 分布式事务解决方案

2PC 两阶段提交

  • 两阶段提交分为两个阶段

    • Prepare Phase 准备阶段
      准备阶段事务管理器给参与者发送prepare消息,每个数据库参与者在本地执行事务,并写入本地的Undo/Redo 日志,此时事务并未提交
      Undo日志是记录修改前的数据,用于数据库回滚, Redo日志是记录修改后的数据,用于提交事务后写入数据文件
    • Commit Phase 提交阶段
      事务管理器接收到所有参与者的执行失败或超时消息后,给参与者发送回滚Rollback或提交Commit消息,并释放所资源
     缺点:
     -同步阻塞 (资源锁定导致阻塞)
     - 单点故障(依赖于事务管理器,事务管理器宕机事务会执行不下去)
     - 数据不一致(网络波动会导致参与者无法收到协调者消息)
    
  • XA方案

    简单的说就是 AP 通过 TM 来定义事务操作,TM 和 RM 之间会通过 XA 规范进行通信,执行两阶段提交,而 AP 的资源是从 RM 拿的。

    • 角色
      • AP:应用程序即分布式事务的程序
      • RM:资源管理器,可以理解为每个事务的参与者
      • TM:事务管理器,负责协调事务和管理事务,事务管理器控制全局事务并协调RM
    • 执行步骤
      • AP持有多个数据节点/数据源RM
      • AP通过TM向RM通知事务执行但并不提交事务,此时资源处于锁定状态;
      • TM收到所有的RM回复后 向所有RM提交事务或回滚事务并释放资源;
    • 缺点:
      • 需要本地数据库支持XA协议、资源需要等到两个阶段提交后才能提交;

3PC 三阶段提交

3PC的引入是为了解决2PC中出现的同步阻塞和较少数据不一致的问题提出的,三阶段提交分为三个阶段:

  • CanCommit 准备阶段 协调者向所有参与者发出包含事务内容的请求,询问是否可以提交事务
  • PreCommit 预提交阶段 协调者根据参与者的反应来执行预提交或abort,预提交即执行事务但不提交事务,abort即回滚事务
  • doCommit 提交阶段 协调者接收到所有的参与者的ACK消息后执行事务提交或回滚操作;若提交阶段无法收到协调者的请求参与者会自动进行事务的提交;

特点:

  • 引入了超时机制,当协调者无法收到参与者的响应时,会自动进行事务的提交;避免了协调者单点故障问题
  • 数据不一致问题仍然存在,如事务需要回滚时网络超时 参与者会自动提交事务导致事务不一致(可以通过添加脚本来自动补偿差异信息)
  • 多了一次网络通讯开销

TCC (Try Confirm Cancel) 应用层的2PC

  1. 2PC与3PC都依赖于数据库的事务提交和回滚,TCC则是一种业务层面或应用层的两阶段提交。TCC主要用于跨数据库、跨服务的业务操作的数据一致性问题。TCC是指Try、Confirm、Cancel也就是业务层对应的三个方法,它分为两个阶段:
  • Try阶段:业务代码调用Try接口进行业务检查和资源预留,比如下单时将下单的库存锁住;
  • Confirm/Cancel阶段:根据try阶段的结果决定执行Confirm接口还是Cancel接口,然后释放锁;
比如有一个扣款服务,我需要写 Try 方法,用来冻结扣款资金,还需要一个 Confirm 方法来执行真正的扣款,
最后还需要提供 Cancel 来进行冻结操作的回滚,对应的一个事务的所有服务都需要提供这三个方法。
  1. TCC的异常处理
  • 空回滚
    场景:进行try时分支事务所在网络异常没有进行被记录为失败,此时调用Cancel方法,此时Cancel方法会进行回滚,但是没有进行记录,导致业务数据不一致;在没有调用Try的情况下调用了二阶段的Cancel方法;
    解决方案:增加分支事务记录表,try方法插入记录表示执行,cancel接口读取记录,如记录存在则正常回滚没否则时空回滚;
  • 悬挂
    场景: 因为网络原因单只cancel消息没有接收或先cancel在try时,相关资源一直被锁定,造成资源悬挂无法释放;
    解决方案:分支事务表中记录执行状态,每次执行前查询状态,try执行时判断cancel是否执行;
  • 幂等实现
    场景:提交阶段异常时出现重复调用confirm和cancel,所以需实现幂等,保证多次执行效果一致;
    解决方案:记录事务执行状态
  1. TCC的特点:通过业务代码实现提交和回滚,对业务的侵入比较大、开发复杂度高、且需要多次DB但是可靠性高、实时性高

SAGA 事务编排、命令协调

  • 概念
    SAGA事务核心思想时将长事务分解成多个本地短事务并依次正常提交,如果所有短事务均执行成功,则分布式事务提交。
    如果出现某个短事务执行本地事务失败,则由SAGA事务协调器协调根据相反的顺序调用补偿操作,回滚已提交的事务。
    每个SAGA事务由一系列幂等的有序子事务组成,每个子事务都有对应的幂等补偿动作,补偿动作等于撤销子事务造成的结果;
  • 恢复策略
  1. 向后恢复,子事务失败后,逆序(反方向)补偿所有已完成的事务,使整个事务的执行结果撤销;
  2. 向前恢复,子事务失败后,会尝试重试事务,确保每个子事务最终都会执行成功,事务失败会重试,无需补偿;
  • SAGA事务的实现方式
  1. 事件编排
事件编排的实现方式是每个服务产生自己的事件并监听其他服务的事件来决定是否采取行动。
在事件编排方法中,第一个服务执行一个事务,然后发布一个事件。该事件被一个或多个服务进行监听,这些服务再执行本地事务并发布(或不发布)新的事件。
当最后一个服务执行本地事务并且不发布任何事件时,意味着分布式事务结束,或者它发布的事件没有被任何 Saga 参与者听到都意味着事务结束。

1)优点
a .避免中央协调器的单点故障风险;
b. 当设计的步骤较少服务开发简单容易实现
2)缺点
a. 服务存在循环依赖的风险;
b. 当涉及步骤较多时,服务间关系混乱、难以追踪调试测试;
2. 命令协调

  命令协调方式基于中央协调器实现(类似于事务管理器)中央协调器(Orchestrator,简称 OSO)以命令/回复的方式与每项服务进行通信,负责协调参与者的事务;中央协调器 OSO 必须事先知道执行整个事务所需的流程,如果有任何失败,
  它还负责通过向每个参与者发送命令来撤销之前的操作来协调分布式的回滚,基于中央协调器协调一切时,回滚要容易得多,因为协调器默认是执行正向流程,回滚时只要执行反向流程即可。

1) 优点
a.服务间关系简单,无循环依赖问题;
b.程序开发简单,降低参与者的复杂性;
c.易维护扩展,添加新步骤时,事务复杂性保持线性,回滚、实施和测试都很容易
2)缺点
a.中央协调器处理逻辑容易变得庞大复杂导致难以维护;
b.存在协调器的单点故障风险

本地消息表

  • 概念
    将分布式事务拆分成本地事务进行处理。在进行本地消息表分布式事务时,参与者分为事务主动方和事务被动方。事务主动方需要新建事务消息表。事务主动方开始事务后需要完成业务处理并记录事务消息。
    然后通过轮询消息表的方式通过消息中间件向事务被动方发送事务消息。事务被动方基于消息中间件消费事务消息表中的事务并返回处理结果。成功,事务主动方更新消息记录表,失败则进行回滚事务;
  • 优点
    • 消息可靠性不依赖于中间件,弱化了对MQ的依赖
    • 方案轻量,容易实现
  • 缺点
  • 与具体业务场景绑定、耦合性强,不可公用;
  • 消息数据与业务数据同库、占用业务系统资源
  • 业务系统在使用关系型数据库的情况下、消息服务性能会受到数据库的并发性能的局限;

MQ事务消息

  • 概念
    MQ事务消息本质上时对本地消息表的封装,唯一不同的是将本地消息表存在了MQ内部,而不是业务数据库中;
  • 优点
    a. 消息数据独立存储,降低了业务系统与消息系统之间的耦合
    b. 吞吐量大于使用本地消息表方案
  • 缺点
    a. 一次消息发送两次网络请求 half消息和commit/cancel消息
    b. 业务处理服务需要实现消息状态回查接口

最大努力通知

  • 概念:
    最大努力通知也称为定期校对,是对MQ事务方案的进一步优化。主要是在事务主动方增加消息校对的接口,即事务被动方没有接收到主动方发送的消息时,被动方可以调用主动方提供的校对接口主动获取

使用场景

  1. 2PC、3PC 提供强一致性和强事务性但延迟较高 适用于传统的单体应用,不适用高并发和高性能要求
  2. TCC 适用于执行时间确定且较短 实时性要求高、数据一致性要求高。比如交易、支付、账务
  3. SAGA 不能保证隔离性,需要在业务层控制并发 适用于补偿动作容易处理的场景
  4. MQ 事务 本地消息表 适用于事务中参与方支持操作幂等,一致性要求不高 事务设计的参与方、参与环节较少 如注册送积分、登录送优惠券、银行通知、支付结果通知等
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值