作为一名程序员,你是不是经常在很多场景,例如看博客、聊天吹水等等时候听到这样一个词"系统数据一致性",是不是有时候感觉到了迷糊,不知道这个"系统数据一致性"到底是在说什么?其实,你可能只是不明白这个词,但是你肯定在实际工作中发现、解决过这样的问题。

单体架构下系统数据一致性问题

在传统的系统应用中,一般都是使用单体架构来构建系统的。即所有的功能模块都放在一起实现,打成一个WAR包部署在Tomcat中,数据一般存放在关系型数据库中,如MySQL数据库。

前面我说过即使这种单体架构的系统也是数据一致性的问题的,举一个电商下单的例子,用户提交完订单,系统,系统在订单表order表中写入订单金额、用户等相关数据,在订单明细order_item表中写入商品价格、购买的数量等数据,最后更新商品的库存sku信息。用户下单成功之后,系统操作了order、order_item、sku这三个数据表,对于这三个表的操作无论成功与失败,都应该是原子的,操作成功则都要成功,失败则都要一起失败。不然就会出现脏数据,数据一致性被破坏。

1、 如果操作order和order_item表成功,操作sku表失败,则会导致本应该扣减的库存没有扣减,则商品有可能出现超卖。

2、如果操作order和order_item表失败,操作sku表成功,则会导致本不应该扣减的库存扣减了,则商品有可能出现少卖。

3、如果操作order和sku表成功,order_item操作失败,则这个订单数据丢失,订单后续的操作肯定也是操作不了了。

上面只是简单的举了三种可能出现的情况,也可能会有其他的情况发生。那我们怎么避免这些情况的发生呢?其实这种问题稍微有的开发经验的同学都会想到解决方案,那就是使用数据库的事务,事务的原子性保证上述的步骤成功则一起成功,失败则一起失败。

BEGIN;
INSERT INTO order;
INSERT INTO order_item;
UPDATE sku;
COMMIT; # ROLLBACK

在单体架构的系统下解决内部模块的数据一致性的问题,用数据库的ACID特性就能保证。

单体架构的优点就是相对分布式来说开发简单,功能可以集中管理,模块之间通信没有损耗。但随着业务越来越复杂、需求越来越庞大,人们对系统响应时间、吞吐量和出现故障的时候的系统可用性的要求也越来越高!传统的单体架构系统在这种情况下暴露的缺点也越来越多,人们开始寻求转变。既然部署在一个服务器上的单体架构系统搞不定,那就多部署几台,即用多台单机节点组成集群,再用负载均衡向外提供服务。

但是这样做还是解决不了单体架构存在的一些问题:

  • 只能使用同种语言开发,不能针对不同业务场景利用不同语言的优势开发对应的模块。
  • 系统模块耦合性太强,系统中某一个模块出现问题,例如高并发、大数据场景或者出现bug,整个系统都会受到牵连。
  • 某个模块发布,整个系统都要停机发布,系统所有模块都不能对外提供服务,这样无法快速响应市场需求。
  • 集群负担大,如果想要集群,只能对整个系统进行集群,即使只有一个模块有压力。

集群(Cluster): 系统单机部署对外服务能力出现瓶颈,则将系统进行多机部署,这些系统对外提供相同的服务,每个单机系统我们称之为节点,多个节点统一起来则可以称之为集群。

分布式架构下系统数据一致性问题

天下大事分久必合、合久必分!既然单体架构解决不了问题,那我们就尝试拆分系统,让专业的人做专业的事,那如何进行拆分呢?拆分一般分为水平拆分和垂直拆分。这里说的拆分并不单指数据库拆分,而是所有模块都进行拆分,每个模块都有自己的缓存、数据库等等。

  • 水平拆分指的是单一的节点无法满足性能的需求,需要进行数量上的扩展。每一个节点都具有相同的功能,每一个节点都负责一部分请求,节点们组成一个集群,对外进行提供服务。
  • 垂直拆分指的是按照功能进行拆分,秉着"专业的人干专业的事",把复杂的系统拆分成各个模块。模块之间通过RPC进行通信,可以做到高内聚、低耦合,每个模块独立部署和维护,可以快速迭代响应市场需求。

因此,分布式架构在这种背景下应运而生。

分布式(Distributed)架构:分布式系统是由集中式系统逐渐演变而来。所谓的集中式系统,就是把系统中所用的功能都集中到一起,从而向外提供服务的单体应用。

软件行业是没有银弹的,每一个被发明出来的新技术,都是一把双刃剑,都是在特定的领域解决了某些老问题,但是同时也会带来新的问题。那么微服务这种分布式架构解决了什么老问题?同时它又带来了哪些新问题呢?

解决了老问题

微服务这种分布式架构主要解决了单体架构存在的一些问题。

  • 各个服务可以使用不同的语言开发,可以利用不同语言的优势开发不同模块。
  • 服务之间可以做到高内聚、低耦合。每个服务可以独立维护、部署,可以快速响应市场需求。
  • 可以单独对某个有高并发、大流量的服务单独进行优化,不浪费资源。

带来了新问题

  • 系统的监控难度加大。
  • 数据的一致性成为问题。
  • 系统的复杂度提高,系统的维护、设计成本增加,调试、纠错难度加大。

新问题中的 数据一致性问题 才是本文接下来的重点。

为啥会有这个数据一致性问题呢?

单体架构按照文中的说法,是一种不太时髦的架构方式,都能轻松解决数据一致性问题,新发明的分布式架构却又成了一个棘手的问题,这个到底是技术的进步还是技术在退步呢?哈哈(我的一点点吐槽)!!接下来我来解释一下为啥分布式系统会有这样的问题。 分布式系统每个功能大都部署在不同的服务器上,部署在不同国家和地区的服务器中,部署在不同的网络中,部署在不同国家和地区的网络中。这样一个需要大量的服务器共同协作,向外提供服务的系统,面临着诸多的挑战:

  1. 良莠不齐的服务器和系统能力

分布式系统中的服务器,可能配置不一样,其上部署的系统可能也是由不同的程序语言、架构实现,因此处理请求的能力也就不一样。

  1. 不可靠的网络

如上文所说,系统中各个服务可能部署在不同国家和地区,各个服务通过网络进行通信,但是网络是不可靠的。网络经常会出现抖动、延时、分割、丢包等问题。 网络通信中最让人头痛的是因为网络抖动、延时等问题导致系统之间的通信出现超时:A服务向B服务发出请求,A服务没有在约定的时间内接受到B服务的响应,你不能确定B服务到底有没有处理完A服务的请求,这样的不确定性就需要我们进行重试处理,那么B服务就要解决请求幂等性问题。

服务器的机房发生火灾、断电等事故。 支付宝出现过服务器的电缆被挖断的问题。

  1. 普遍存在的单点故障

分布式系统为了保证故障发生的时候,系统仍然保证可用,每个模块都采用集群部署。单个节点的故障概率较低,但是节点数量达到一定规模时,系统中的节点出现故障的概率可能就变高了。

分布式系统就是这样一些处在不同区域、有着不同能力和拥有单一功能的服务组成,他们通力合作才能向外提供服务,那如何保证他们的状态、信息一致并且协调有序就成了一个难题。

分布式系统就是要解决解决集中式的单体架构系统的各种缺陷,实现整个系统的 高性能 、高可用、可扩展,但是要实现这三个目标并不容易,将系统进行拆分的过程中会出现上文中说到的问题,为了解决这些问题,诞生了很多关于分布式的基本理论,比如CAP、BASE等等。

分布式架构有很多相关的理论和算法,这里我只说了CAP、BASE理论,其他诸如Paxos算法、Raft算法、ZAB协议等等,这些大家自己找资料看看吧!

我们先来说说CAP理论

这个CAP理论相信很多人都听说过,下面请允许我写下教科书般的理论内容:

CAP原则又称CAP定理,指的是在一个分布式系统中,Consistency(一致性)、 Availability(可用性)、Partition tolerance(分区容错性),三者不可得兼。

一致性(C):在分布式系统中的所有数据备份,在同一时刻是否同样的值,也就是等同于所有节点访问同一份最新的数据副本。 可用性(A):保证每个请求不管成功或者失败都有响应,即使数据不是最新的。 分区容忍性(P):系统中的某个节点或者网络分区出现了故障的时候,整个系统仍然能对外提供的服务。

什么情况?这个CAP理论上来就给出三个概念或者说是指标,还说分布式系统只能满足上面两个指标。大家是不是经常听到CAP理论,但是却又不是很理解为什么CAP三个指标只能满足其中的两个,那么接下来我给大家解释一下:

就如前面的“分布式架构图”展示的一样,系统一个对外的服务涉及到多个节点通讯和交互,节点所处的网络发生分区故障的问题又无法避免,所以分布式系统中分区容错性必须要考虑,那么系统自然也不可能同时满足上面说的三个指标。

分布式系统中CAP如何抉择?

在分布式系统内,各种因素导致分区是必然的会发生的,不考虑分区容忍性(P),一旦发生分区错误,整个分布式系统就完全无法使用了,这其实和最开始的单体应用一样有单点问题,这样的系统是和分布式架构理论是相违背的,同时也是不符合实际需要的。所以,对于分布式系统,我们只能能考虑当发生分区错误时,如何选择一致性(C)和可用性(A)。

根据一致性和可用性的选择不同,开源的分布式系统往往又被分为 CP 系统和 AP 系统。 当系统在发生分区故障后,客户端的任何请求都被阻塞或者超时,但是,系统的每个节点总是会返回一致的数据,则这样的系统就是 CP 系统,经典的比如 Zookeeper。 当系统发生分区故障后,客户端依然可以访问系统,但是获取的数据是不一致的,有的是新的数据,有的还是老数据,那么这样系统就是 AP 系统,经典的比如 Eureka。

前面说分布式系统不考虑分区容忍性(P)为啥分区错误发生,系统就不能用了,这里我再解释一下: 不考虑分区容忍性(P),那就是选择CA。假设发生了分区错误,系统由于可用性(A)的要求,即使系统发生分区故障也要提供服务,那系统就仍然向外提供服务,因为服务肯定的包含对数据的读取、写入、更新、删除,可是由于一致性(C)的要求,系统中所有的节点数据都要保持一致,因为分区错误发生,节点的数据同步肯定无法进行,数据副本的一致性就无法保证,那就不能像对外提供服务。那这样CA就相互矛盾,系统无法保证可用性(A)和一致性(C),系统自然是不能使用了,也就是说没有选择CA的分布式系统,而且这分区容忍性(P)必须要考虑!而且,不是一个系统选择了可用性(A)或者一致性(C),可以是其中的模块选择了可用性(A)和一致性(C)

Zookeeper常常有人用它作为dubbo的注册中心,Eureka作为Spring Cloud体系中的注册中心,其实对于注册中心角色来说,我觉得Eureka比Zookeeper更适合!

还有一点这里我说一下,其实大部分情况下分布式系统是没有问题的,C和A两个指标都是同时满足的,只是在分区问题发生的情况下,才需要我们考虑到底是选择C还是A。

前文说到解决单点故障的问题,我们引入了集群。在分布式系统中我们为了提高系统的可用性,也是不可避免的使用副本的机制,引入了副本则就需要同步数据到不同的副本,从而引发了副本一致性的问题。就如前面展示的“分布式架构图”中,会员、订单和产品服务都是独立部署且分别使用不同的数据库,每个服务内部又是使用数据库集群,数据在服务与服务之间、在某个服务的数据库集群中间等等的流转、同步,这些过程都是有网络、时间消耗的,一个数据从最开始的产生到它应该到的地方不会瞬时完成,而CAP理论是基于瞬时,在同一时刻任意节点都保持着最新的数据副本,它是忽略网络延迟、节点处理数据的速度的,这个在目前的技术下是不可能做到的,从这个角度来看,CAP理论实在是乐观主义了。

CAP理论的缺点是什么?

CAP理论其实是有缺点的,前文也提到一些,具体的缺点如下:

  • 理论忽略网络延迟、节点处理数据的速度

CAP的理论的作者布鲁尔在定义一致性时,并没有将上述的问题考虑进去。即当事务提交之后,数据能够瞬间复制到所有节点。但实际情况下,数据从产生到复制到各个服务、各个节点,总是需要花费一定时间的。如果在相同机房可能是几毫秒,如果跨地域、跨机房,可能是几十毫秒甚至是一百多毫秒。这也就是说,CAP理论中的C在实践中是不可能完美实现的,在数据副本的同步的过程中,节点之间的数据在一个短时间内并不一致。

  • 理论中的一致性是强一致性

CAP理论中的一致性的概念是,在分布式系统中的所有数据备份,在同一时刻是否同样的值,也就是等同于所有节点访问同一份最新的数据副本。在某些场景下这种强一致性要求并不是那么高。在一个日志搜集系统,在高并发、大数据的情况下,一条日志写入需要稍后一会才能在ELK中展示出来,这样是没有问题的。通过牺牲强一致性获得可用性,在一定时间之后最终数据达成一致性即可。

  • 理论中的指标的选择和放弃并不是三选二的关系

CAP理论告诉我们三者只能取两个,需要放弃另外一个,这里的放弃是有一定误导作用的,因为“放弃”让很多人理解成什么也不做。实际上,CAP理论的“放弃”只是说在系统分区错误过程中,我们无法同时保证C和A,但并不意味着什么都不做。分区期间放弃C或者A,并不意味着永远放弃C和A,我们可以在分区期间进行一些操作,从而让分区故障解决后,系统能够重新达到CA的状态。最典型的就是主从数据库中主数据挂了,后面进行修复,使得重新达到CA状态。

CAP理论的改进版BASE理论

由于CAP理论在定义时过于的乐观,导致他有些缺陷,于是又有大神改进了CAP理论,从而引申出理论改进版本:BASE理论。eBay的架构师Dan Pritchett根据他自身在大规模分布式系统的实践经验,提出了BASE理论。BASE理论是对CAP理论的延伸和补充,它满足CAP理论,通过牺牲强一致性获得可用性,在一定的时间窗口内,达到数据的最终一致性。

BASE理论模型包含如下三个元素:

  • BA:Basically Available,基本可用。
  • S:Soft State,软状态,状态可以在一定时间内不同步。
  • E:Eventually Consistent,最终一致性,在一定的时间窗口内,最终数据达成一致即可。

Basically Available 基本可用

BASE理论中的Basically Available 基本可用,就是系统在出现问题的时候,牺牲一部分的功能,来保障核心功能正常。这其实就是一种妥协,相当于壁虎断臂求生。 就像前几年的双十一淘宝,订单支付、退款直接崩掉了,后面就进行改进限流需要你多试几次才能付款、退款,再后来双十一那几天是不能申请退款的,直接就把你这个功能给关闭了,相当于服务熔断了。这就是牺牲非核心的功能,将所有的资源都用来保障核心的支付功能。

Soft State,软状态

允许系统在一定时间内的状态不同步,允许系统处于软状态,这个软状态其实就是中间状态。比如采用分布式架构的电商系统,用户下单完成并付款,是否支付成功,是支付系统完成的,订单系统不会等支付系统返回是否支付成功再把结果返回给客户的,而是先把订单状态设置为付款中,返回给客户,然后支付系统收到异步通知确定支付成功成功,再把状态设置为付款完成,再把付款完成信息推送给订单系统。这样,就可以提高系统的响应速度。即使这支付系统出现故障宕机了,系统重启之后可以通过定时任务补偿处理未完成的数据,然后根据数据所处的状态进行补偿处理,最终完成数据处理。付款中这个状态,就是软状态即中间状态。

Eventually Consistent,最终一致性

数据不会一直处在中间状态,就如上面的例子所说,处于中间状态的数据会有采用类似定时任务一样的补偿处理,将数据修复成正确的状态,最终数据达成一致。

重说“带来了新问题”

前文说到分布式架构解决了单体架构的一些问题,但是同时也带来了一些新的问题,这里我们着重说一下,本来不是大问题的“数据一致性”问题。前面举了一个电商系统中的经典案例:下订单与扣库存。单体架构的应用我们直接用数据库事务的ACID特性就可解决,但是采用分布式架构的系统就没有那么好解决了,我们先说一下在分布式架构下的系统是如何完成“下订单与扣库存”的,这里就不画图了直接用伪代码来展示:

public void buildOrder(OrderDto orderDto) {// 1.保存订单orderService.saveOrder(orderDto);// 2.扣除产品库存inventoryService.deductInventory(orderDto);
}

这步骤一保存订单是在订单系统中执行,步骤二扣除产品库存是在库存系统执行,这个下订单与扣库存两个步骤分别涉及到了两个系统,使用RPC的方式和两个系统进行交互。由于这两个步骤不是原子的,不能保持一致的话会导致很多的问题:

  • 比如先保存订单成功,然后扣除产品库存失败,那订单就要回滚处理;
  • 如果先扣除产品库存成功,然后保存订单失败,那库存就要回滚;
  • 或者说先保存订单然后扣除产品库存时请求超时,其实库存已经扣除成功等等问题。

这些问题你不解决,就有可能导致产品多卖或者是产品出现少卖,不管出现哪个都会造成资损或者客诉,任何一种情况都不是我们想发生的。

由于库存系统和订单系统分别使用各自的数据库,那原先使用数据库事务的ACID特性保证数据的一致性就不能奏效了,分布式架构的系统就产生了数据一致性的问题,这种跨多个数据库的事务问题,其实就是分布式事务问题。要解决分布式架构的系统的数据一致性问题,其实就是解决分布式事务的问题。

目前业界也出现了很多分布式事务的解决方案,例如两阶段提交2PC、三阶段提交3PC、TCC还有基于可靠消息等方案,他们用不同的方案实现分布式事务,解决数据一致性的问题,这里就不再详述。

基于可靠消息解决分布式事务,解决数据一致性的问题,其中一种方案叫做本地消息表,这种方案名称大家可能不知道,但是你很有可能这样做过,这个后面的文章再细说。

系统的数据一致性到底是在说什么?我到今天才算真明白了相关推荐

  1. 英语四级和计算机一级算多少学分,英语四六级,到底是425分,还是426分才算过?...

    文|学个习 原创文章,著作权归作者所有,欢迎转发分享! 英语四.六级考试(CET),相信,每一个大学生都不会陌生. 这是教育部主办,教育部考试中心主持实施的大规模标准化考试. 其目的是为了促进我国大学 ...

  2. 鸿蒙系统和汽车,华为鸿蒙系统和新日电动车,到底是什么关系?

    华为鸿蒙系统和新日电动车,到底是什么关系? 2021年05月31日 11:13作者:网络编辑:王动 分享 近日,华为鸿蒙系统即将正式上线的消息在全网刷屏,自Harmony OS发布以来,华为始终强调: ...

  3. 32位系统的X86到底能支持多大内存

    微软最新Windows Server 2008 R2 \ 以及最新的Microsoft Office SharePoint ( MOSS ) 2010 \ Project Server 2010 \ ...

  4. 【diannaoxitong】系统字体模糊到底是哪几方面造成

    您所在的位置: 电脑系统 > 操作系统 > 电脑城 使用集成显卡的电脑系统用久了之后,会出现显示器屏幕字体模糊的现象,在液晶显示器上发生的尤为明显.显示字体模糊是可以预防的.笔者给大家分析 ...

  5. 到底多大并发才算高并发?一文带你全面认识高并发!

    点击上方蓝色小字,关注"涛哥聊Python" 重磅干货,第一时间送达 作者 | 骆俊武 来源 | IT人的职场进阶 高并发,几乎是每个程序员都想拥有的经验.原因很简单:随着流量变大 ...

  6. 到底多大并发才算高并发?

    高并发,几乎是每个程序员都想拥有的经验.原因很简单:随着流量变大,会遇到各种各样的技术问题,比如接口响应超时.CPU load升高.GC频繁.死锁.大数据量存储等等,这些问题能推动我们在技术深度上不断 ...

  7. 什么才算好的监控系统?

    什么才算好的监控系统? 我们可以这样理解,监控系统就像我们的眼睛,帮助我们了解记录系统到底发生什么,帮助我们管理.运维整个系统.所以全栈监控其实非常非常关键. 而在分布式或 Cloud Native ...

  8. 上海交大的微电子学院计算机科学与技术 与 电子信息 区别,电子科学与技术和电子信息工程,到底有啥差别?学姐给你讲个明白...

    原标题:电子科学与技术和电子信息工程,到底有啥差别?学姐给你讲个明白 大学什么专业就业最好?大家都知道工科是计算机和软件,以及电子信息类专业,当然计算机也属于广义上的电子信息类专业. 一般广义的电子信 ...

  9. 华为手机怎样才算激活了_外观专利到底怎样才算侵权呢?

    外观专利到底怎样才算侵权呢? 外观设计的侵权判定: 一.确定外观设计专利权的保护范围 根据专利法第五十九条第二款之规定,其保护范围,以表示在外观设计专利权人在申请外观设计专利时向专利局提交的图片或者照 ...

最新文章

  1. easyVMAF:在自然环境下运行VMAF
  2. h5页面点击事件ios没反应 移动端兼容性问题
  3. Resource Hacker+mysql安装会出现错误“应用程序无法启动因为应用程序的并行配置不正确”...
  4. 【经验分享】为什么后台取到的时间和前台差8个小时?
  5. 2021年十大 web hacking 技术汇总
  6. Linux 命令(106)—— chkconfig 命令
  7. linux ssh-keygen命令生成密钥 -t -C参数说明
  8. springboot毕业设计 基于springboot房产中介预约看房系统毕业设计设计与实现参考
  9. 基于SSM的汽车租赁系统
  10. 什么是Cisco ACI?
  11. Guitar Pro8吉他打谱下载自学制作教程
  12. java视频教程,Java面试资料
  13. 软件安全漏洞测试报告_现实生活中的软件安全漏洞以及如何确保安全
  14. NVIDIA TensorRT (python win10)安装成功分享
  15. 苹果6s连上wifi上不了网络连接服务器未响应,6s连不上网了怎么解决
  16. 程序员转行能做什么?
  17. 2022全新Java学习路线图动力节点(七)架构师必备技术
  18. 闲人闲谈PS之一项目库存跨公司业务STO解决方案--SAP闲人的开篇
  19. 9.数据中台 --- 数据服务体系建设
  20. Head FIrst OOAD 读书笔记

热门文章

  1. 软件构造 lab-1 Problem Set 1: Tweet Tweet(MIT)
  2. 基于ARM核心板实现的BMS可行性方案
  3. tplink打印机服务器重置,TP-Link TL-WDR7500无线路由器如何打造打印机共享服务器
  4. 关于safiry开启无痕浏览时本地存储的处理
  5. 电脑重装Win10如何选择32位和64位的系统
  6. 电子设计之硬件开发流程和前辈的指导
  7. 函数指针的作用:*visit函数
  8. Java项目:游戏点评系统(java+SSM+JSP+JavaScript+mysql)
  9. 痞子衡嵌入式:揭秘i.MXRTxxx系列上串行NOR Flash双程序可交替启动设计
  10. MindManager Mac苹果版本教程激活码序列号秘钥下载详情