分布式系统的一致性问题

分布式系统的一致性问题

有哪些一致性问题?

  • 订单库存场景

  • 同步调用超时/异步调用超时

  • 掉单场景

  • 缓存与数据库不一致

为什么要解决一致性问题?

确保其状态、数据的一致性,面对具体的业务场景进行架构设计才能更可靠。

面向高并发、高可用、依赖治理、持续SRE(持续稳定性工作)

  • 高并发:QPS,TPS每秒达到几千甚至上万或者更高,我们需要从那几个方面来总和考虑?

  • 高可用:服务不存在单点问题,核心链路降级、兜底策略和手段。

  • 依赖治理:梳理业务核心的相互依赖关系,进行强弱划分,针对强弱依赖如何处理?

  • SRE:针对服务的稳定、可靠、可用性的持续运维和优化工作。

1.订单库存场景(超卖)

下单和扣库存如何保持一致,如果下单成功,扣库存失败,则会导致超卖;

方案:

  • 尽量保证订单和库存放在同一个数据库分片中。

  • 如果不能在数据库层面设计,就要实现最终一致性了。

  • 对每个步骤记录一个状态,根据状态做定时任务做补偿。保证幂等性,通过乐观锁的机制实现。例如增加版本号,更新前先查询版本号再更新,防止并发时多个线程对同一条数据做更新。

    update order set count=count -1 , version = version +1 where id = 123456 and version= 10

2.同步调用超时/异步调用超时

服务化系统之间因为网络问题导致系统调用超时,调用后,逻辑处理成功,但是响应超时。

方案:1.做超时熔断策略(快速失败)

2.补偿策略(主动查询补状态)

3.掉单问题

在分布式系统中,两个系统 协作处理一个流程,一个请求,A系统存在,B系统不存在,则会导致掉单。

方案:设计DNA做补单策略

4.缓存与数据库不一致

在处理高并发的场景下,通过增加缓存来提供系统响应能力,可能会产生这个问题。

分布式系统的核心概念

ACID

数据库的4个特性

  • 原子性(atomicity)

    一个事务要么全部提交成功,要么全部失败回滚,不能只执行其中的一部分操作,这就是事务的原子性

  • 一致性(Consistency)

    事务的执行不能破坏数据库数据的完整性和一致性,一个事务在执行之前和执行之后,数据库都必须处于一致性状态。

  • 隔离性(Isolation)

    事务的隔离性是指在并发环境中,并发的事务时相互隔离的,一个事务的执行不能不被其他事务干扰。不同的事务并发操作相同的数据时,每个事务都有各自完成的数据空间,即一个事务内部的操作及使用的数据对其他并发事务时隔离的,并发执行的各个事务之间不能相互干扰。

  • 持久性(Durability)

    一旦事务提交,那么它对数据库中的对应数据的状态的变更就会永久保存到数据库中

但是在高并发、大数据量访问的互联网应用,一般不推荐使用事务,因为增加事务和性能二者之间是不可协调的。

CAP

概念:CAP原则又称为帽子理论,指的是再一个分布式系统中,一致性、可用性、分区容错性,三者不可兼得。

  • 一致性(Consistency):数据一致更新,所有数据变动都是同步的。

  • 可用性(Availability):集群中部分节点故障后,集群整体还能对外提供服务。

  • 分区容错性(Partition tolerance):分区相当于对通信时限的要求;尽管网络有部分消息丢失,但系统任可持续工作。如果系统不能在一定时间内达成数据一致,就意味着发生了分区的情况,必须在当前操作C和A之间做出选择。

  • CAP原理证明任何分布式系统只可以同时满足2点,无法三者兼顾。

Zookeeper:CP模式

Spring Cloud 中的 Eureka:AP模式

BASE理论

对应CAP理论的解决思想理论,它解决了CAP理论所提出的分布式系统的 一致性和可用性不可兼得的问题。

BASE是Basically Available(基本可用)、Soft state (软状态)和Eventually consistent(最终一致性)三个短语的简写,BASE是对CAP中的一致性和可用性权衡的结果,来源于大规模互联网分布式实践的结论,核心思想是即使无法 做到强一致性,但每个应用根据自身特点采用适当地方式来达到最终一致性

  • BA:基本可用

  • S:软状态,状态可以再一段时间内不同步 ,业务可以容忍。

  • E:最终一致性,在一定的时间窗口内,数据达成最终一致。

分布式系统一致性解决方案

首先,以下所有的方案都有自己的缺陷。在高并发大数据了的互联网应用是不做分布式事务的,如果非要做,可以考虑第三种方案。

分布式事务在业界有哪些解决方案?

  • 两阶段提交协议(不推荐使用)
  • 三阶段提交协议(不推荐使用)
  • 使用MQ处理分布式业务场景(还有一定的可行性)
  • TCC柔性事务解决方案(不推荐使用)

两阶段提交

具体可参考:https://my.oschina.net/codingcloud/blog/4938966

2PC,所谓的两个阶段是指:第一阶段:**准备阶段(投票阶段)**和第二阶段:提交阶段(执行阶段)

2PC提交操作

success

2PC回滚操作

fail

1、同步阻塞问题。执行过程中,所有参与节点都是事务阻塞型的。当参与者占有公共资源时,其他第三方节点访问公共资源不得不处于阻塞状态。

2、单点故障(也就是脑裂)。由于协调者的重要性,一旦协调者发生故障。参与者会一直阻塞下去。尤其在第二阶段,协调者发生故障,那么所有的参与者还都处于锁定事务资源的状态中,而无法继续完成事务操作。(如果是协调者挂掉,可以重新选举一个协调者,但是无法解决因为协调者宕机导致的参与者处于阻塞状态的问题)

3、数据不一致。在二阶段提交的阶段二中,当协调者向参与者发送commit请求之后,发生了局部网络异常或者在发送commit请求过程中协调者发生了故障,这回导致只有一部分参与者接受到了commit请求。而在这部分参与者接到commit请求之后就会执行commit操作。但是其他部分未接到commit请求的机器则无法执行事务提交。于是整个分布式系统便出现了数据部一致性的现象。

4、二阶段无法解决的问题:协调者再发出commit消息之后宕机,而唯一接收到这条消息的参与者同时也宕机了。那么即使协调者通过选举协议产生了新的协调者,这条事务的状态也是不确定的,没人知道事务是否被已经提交。

三阶段提交

具体可参考:https://my.oschina.net/codingcloud/blog/4938966

三阶段提交(Three-phase commit),也叫三阶段提交协议(Three-phase commit protocol),是二阶段提交(2PC)的改进版本。

与两阶段提交不同的是,三阶段提交有两个改动点。

1、引入超时机制。同时在协调者和参与者中都引入超时机制。
2、在第一阶段和第二阶段中插入一个准备阶段。保证了在最后提交阶段之前各参与节点的状态是一致的。

也就是说,除了引入超时机制之外,3PC把2PC的准备阶段再次一分为二,这样三阶段提交就有CanCommitPreCommitDoCommit三个阶段。

3

了解了2PC和3PC之后,我们可以发现,无论是二阶段提交还是三阶段提交都无法彻底解决分布式的一致性问题。Google Chubby的作者Mike Burrows说过, there is only one consensus protocol, and that’s Paxos” – all other approaches are just broken versions of Paxos. 意即世上只有一种一致性算法,那就是Paxos,所有其他一致性算法都是Paxos算法的不完整版。

MQ分布式事务

rocketMQ收费版是目前唯一支持分布式事务的消息中间件,开源版是不支持的。

推荐阅读:https://www.jianshu.com/p/468176c6bc1b

TCC柔性事务

TCC你可以理解为是专门针对于分布式场景的一种实现策略或者说协议,TCC把一个分布式的请求任务拆分成了Try、Confirm、Cancel三个步骤,正常的流程肯定先会执行Try,如果执行没问题,再执行Confirm,如果执行过程中出现了超时或者异常等问题,则执行Cancel操作。从正常的角度去想,这仍然是一种两阶段提交协议的思想,但是其好处是在执行出现问题之后有一定的自我恢复能力,如果任何参与者出现了问题则协调者通过执行操作的逆向操作来回滚之前的所有操作,从而达到最终一致状态。当然TCC也有它的问题所在,在极端情况下,可能出现有些参与者收到命令,有些没有收到命令的时候,那么系统首先就会通过自动补偿的方式尝试自动修复或者重试,如果无法修复成功则只能由人工参与解决。

最佳分布式一致性解决方案

满足我们的分布式需求、高并发高性能以及吞吐量为前提下,我认为分布式服务的一致性一定要以可靠性为基础、简洁性为目标去考量方案。我总结了几种比较高效的处理模式。

  • 主动查询模式

    所有的操作都提供一个查询接口,用于向外部输出操作执行的状态,服务操作的使用方可以通过查询接口而得知服务操作执行的状态。然后根据不同的状态来做不同的处理操作。

  • 补偿模式

    通常与主动查询模式结合使用,目的都是为了实现上下游的服务最终一致性的努力确保机制。

  • 异步确保模式\可靠性消息模式

    这两种模式也是互联网行业中经常需要使用的经典模式,很多时候我们的使用方对响应时间 要求不太高、或者说不需要特别强调实时性的场景,这一类的操作我们经常采用异步化、或者解耦的方式,把其从主流程(核心链路上摘除) ,或者说我们划分好业务边界,然后再可以容忍的窗口期内做异步确保和发送可靠性消息模式。这个方案最大的好处是能够对高并发流量进行削峰,从而对服务上能够提供解耦。比如我们电商系统中的物流、配送等,金融系统中的支付、计费入账等等

  • 定期校对模式

    这种方式多用于互联网金融行业,一般都是针对商户与平台与银行等第三方金融支付平台之间的一个经典场景,因为涉及资金安全,所以对于互联网金融行业会对其进行多重的一致性保证机制,比如商户交易对账、系统间一致性对账、财务对账等等。这种也是针对于场景而言的。一般对实时性要求最低,但是对准确性、一致性要求最高

缓存一致性的问题

在大规模分布式的系统中,一个场景的核心需求就是亿级别的读需求,显然关系型数据库不是解决高并发的最佳方案,互联网行业通常的做法就是使用缓存来抗住读流量,那么如何保障缓存和数据库的一致性,我也大概汇总和划分几点必须要做和清楚的事情

  • 如果性能要求不是非常高,则尽量使用分布式缓存,不要使用本地缓存。

  • 写缓存时数据一定要完整,如果缓存数据一部分有效,另一部分无效,则宁可在需要时回源数据库抽取,也不要把部分数据放入缓存。

  • 使用缓存就牺牲了一致性,为了提高性能,数据库与缓存只能保证且只需要保持弱一致性即可,否则其他的做法即违背了缓存的目的也浪费了太多的系统性能

  • 读的顺序是先读缓存再读数据库,写的顺序一定要先写数据库再写缓存。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值