分布式与一致性协议之CAP(三)

devtools/2024/9/23 6:38:43/

CAP_0">CAP

CAP_1">ACID理论:CAP的"酸",追求一致性

提到ACID,它很容易理解,在单机上实现也不难,比如可以通过锁、时间序列等机制保障操作的顺序执行,让系统实现ACID特性。但是一说要实现分布式系统的ACID特性比较难实现呢?
ACID理论是对事务特性的抽象和总结,方便我们实现事务。可以这样理解:如果实现了操作的ACID特性,那么旧实现了事务。二大多数人觉得比较难,是因为分布式系统涉及多个节点间的操作。加锁、时间序列
等机制只能保证单个节点上操作的ACID特性,无法保证节点间操作的ACID特性。那么怎么做才会让实现不那么难呢?答案是通过分布式事务协议实现,比如二阶段提交协议和TCC(Try-Confirm-Cancel),不过在介绍二阶段提交协议和TCC之前,咱们先继续看看苏秦的故事,看这回苏秦又遇到了什么事。

最近呢,秦国按耐不住自己躁动的新,开始骚扰魏国边境,魏王头疼,向苏秦求助,苏秦认为"三晋一家亲",建议魏王联合赵、韩一起对抗秦国。但是这三个国家实力都很弱,需要大家都同一联合,一致行动,如果有
任何一方不方便行动,就取消整个计划。根据侦察情况,明天发动反攻的胜算比较大。所以苏秦想协调赵、魏、韩明天一起行动,如图所示,那么对于苏秦来说,他面临的问题是,如何高效协同赵、魏、韩一起行动,
并且保证当有一方不方便行动时,取消整个计划。苏秦面临的这个新问题,就是典型的如何实现分布式事务的问题。赵、魏、韩明天攻打秦国,这三个操作组成一个分布式事务,要么全部执行,要么全部不执行。
了解了这个问题之后,我们来看看如何通过二阶段提交协议和TCC帮助苏秦解决这个难题
在这里插入图片描述

二阶段提交协议

二阶段提交协议,顾名思义,就是通过二阶段的协商来完成一个提交操作,那么具体是怎么操作的呢?
首先,苏秦发消息给赵,赵接收到消息后就扮演协调者(Coordinator)的身份联系魏和韩发起二阶段提交,如图所示。
在这里插入图片描述

赵发起二阶段提交后,先进入提交请求阶段(又称投票阶段)。为了方便演示,我们先假设赵、魏、韩明天都能去攻打秦国,大致步骤如图所示。
在这里插入图片描述

也就是说,第一步,赵分别向魏、韩发送消息:“明天攻打秦国,方便么?”
第二步,赵、魏、韩分别评估明天能否去攻打秦国,如果能,就预留时间并锁定,不再安排其他军事活动
第三步,赵得到全部的回复结果(包括他自己的评估结果),都是YES
赵收到所有回复后,进入提交执行阶段(又称完成阶段),大致步骤如图所示
在这里插入图片描述

首先,赵按照"要么全部执行,要么放弃"的原则,统计投票结果,因为所有的回复结果都是YES,所以赵决定执行分布式事务:明天攻打秦国。
然后,赵通知魏、韩:“明天攻打秦国”。接到通知之后,魏、韩执行事务,明天攻打秦国。最后,魏、韩执将执行事务的结果返回给赵。
这样依赖,赵就将事务执行的结果(也就是赵、魏、韩明天一起攻打秦国)返回给苏秦,那么,这时苏秦就解决了问题,协调好了明天的作战计划。
在这里,赵采用的方法就是二阶段提交协议,在这个协议中:

  • 1.可以将"赵明天带兵攻打秦国、魏明天攻打秦国、韩明天带兵攻打秦国"理解成一个分布式事务操作
  • 2.可以将赵、魏、韩理解为分布式系统的3个节点,其中,赵是协调者。将苏秦理解为业务,也就是客户端
  • 3.可以将消息理解为网络消息
  • 4.可以将"评估明天是否方便,预留时间"理解为评估事务中选哟操作的对象和对象状态,是否准备好,能否提交新操作。

需要注意的是,在第一个阶段,每个参与者投票表决事务是放其还是提交。一旦参与者投票要求提交事务,那么就不允许放弃事务。也就是说,在一个参与者投票要求提交事务之前,它必须保证能够执行提交协议中
它自己的那一部分,即是参与者出现故障或者中途被替换掉。这个特性是我们需要在代码实现时保障的。
还需注意的是,在第二个阶段,事务的每个参与者执行最终统一的决定,提交事务或者放弃事务。这个约定是为了实现ACID中的原子性。

二阶段提交协议最早是用来实现数据库的分布式事务的,不过现在最常用的是XA协议。XA协议是X/Open国际联盟基于二阶段提交协议提出的,也叫X/Open DTP(Distributed Transaction Processing)模型,比如
MySQL就通过MySQL XA实现了分布式事务(MySQL中的XA事务需要将事务隔离级别设置为串行化)。
但是不管是原始的二阶段提交协议,还是XA协议都存在一些问题:

  • 1.在提交请求阶段,需要预留资源,在资源预留期间,其他人不能操作(比如XA协议在第一阶段会将相关资源锁定):
  • 2.数据库是独立的系统。
    因为上面这两点,我们无法根据业务特点弹性地调整锁地粒度,而这些都会影响数据库地并发性能。那用什么办法可以解决这些问题呢?答案就是TCC

TCC

TCC是Try(预留)、Confirm(确认)、Cancel(撤销)3个操作的合称,它包含了预留、确认(或撤销)两个阶段。那么如何使用TCC协议解决苏秦面临的问题呢?
首先,我们进入预留阶段,大致步骤如图所示
在这里插入图片描述

第一步,苏秦分别通知赵、魏、韩预留明天的时间和相关资源。然后诉求你注册确认操作(明天攻打秦国)和撤销操作(取消明天攻打秦国)。
第二步,苏秦收到赵、魏、韩的预留答复,都是Success.

如果预留节点的执行都没有问题,则进入确认阶段,大致步骤如图所示
在这里插入图片描述

第一步,苏秦执行确认操作,通知赵、魏、韩攻打秦国
第二步,收到确认操作的响应,完成分布式事务。

如果预留阶段执行出错,比如赵的一部分军队还在赶来的路上,无法出兵,那么就将进入撤销阶段,大致步骤如图所示
在这里插入图片描述

第一步,苏秦执行撤销操作,通知赵、魏、韩取消明天攻打秦国的计划
第二步,收到撤销操作的响应。
在经过了预留和确认(或撤销)阶段的协商,苏秦实现这个分布式事务:赵、魏、韩三国,要么明天一起进攻,要么明天都按兵不动。其实在我看来,TCC本质上是补偿事务,它的核心思想是为每个操作都注册一个与其对应的确认操作和补偿操作(也就是撤销操作)。它是业务层面的协议,你也可以将TCC理解为编程模型。TCC的3个操作是需要在业务代码中编码实现的,为了实现一致性,确认操作和补偿操作必须是幂等的,因为这两个操作可能需要失败重试。

另外,TCC不依赖于数据库的事务,而是在业务中实现了分布式事务,这样能减轻数据库的压力,但对业务代码的入侵性更强,实现的复杂度
也更高。所以推荐在需要分布式事务能力的时候,优先考虑线程的事务型数据库,比如MySQL XA,在现有的事务型数据库不能满足业务需求
的时候,再考虑基于TCC实现分布式事务。

补充

最后补充一下,三阶段提交协议虽然针对二阶段提交协议的"协调者故障,参与者长期锁定资源"的痛点引入了询问阶段和超时机制来减少资源
被长时间锁定的情况,不过这会导致集群各节点在正常运行的情况下,使用更多的消息进行协商,增加了系统负载和响应延迟。因此,不建议
使用三阶段提交协议,

注意

可以将ACID特性理解为CAP一致性的边界,最强的一致性,也就是CAP的"酸"(Acid)。根据CAP理论,如果分布式系统中实现了一致性
那么可用性必然受到影响。比如,如果出现一个节点故障,则整个分布式事务的执行都是失败的。实际上,绝大部分场景对一致性要求没那么高,短暂的不一致时能接受的,另外,基于可用性和并发性能的考虑,建议在开发实现分布式系统时,如果不是必须,尽量不要实现ACID而是考虑实现最终一致性


http://www.ppmy.cn/devtools/22795.html

相关文章

生成对抗网络的无载体信息隐藏算法简介

一、研究背景 随着互联网技术的广泛应用和移动智能设备的快速普及,人们有了更多的途径传播和获取信息。每天海量的数据以视频、音频、图像、文字等各类形式在互联网中产生,这为人们的生活带来了极大的便利,但同时也引起了人们对信息泄露的担…

【prometheus】k8s集群部署AlertManager实现邮件和钉钉告警

目录 一、AlertManager概述 1.1 alertmanager简介 1.2 AlertManager核心概念 1.2.1 分组 1.2.2 抑制 1.2.3 静默 1.2.4 客户的行为 1.2.5 高可用性 二、Alertmanager部署邮箱告警 2.1 邮箱配置 2.2 Alertmanager global和route路由配置 2.3 部署prometheus和alertM…

【c++】【贪心】排队接水

排队接水 题目难度:中阶 时间限制:1000ms 内存限制:128MB 题目描述 有 n 个人在一个水龙头前排队接水,假如每个人接水的时间为 Ti,请编程找出这 n 个人排队的一种顺序,使得 n 个人的平均等待接水时间最…

中信银行深耕养老金融,构建多支柱养老金体系新格局

在应对人口老龄化这一全球性挑战的过程中,养老金融已成为中国金融领域的重要篇章。2024年4月25日,中信银行行长刘成在财新传媒主办的“2024中国养老产业论坛”上发表主旨演讲,深入阐述了养老金金融、养老服务金融、养老产业金融互促互进的大趋…

Hibernate:Caused by: java.lang.ClassNotFoundException: oracle.sql.BLOB

在spring里插入 BLOB字段 kp.setContent(content.getBytes()) 方法 :hibernate saveOrUpdate 报 Caused by: java.lang.ClassNotFoundException: oracle.sql.BLOB 使用tomcat 没问题,可服务器改为 WebSphere .就报错。 把Spring内置提供的NativeJdb…

【后端】python中字典合并的方法

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、python中字典简介二、python中字典合并的方法三、总结 前言 随着开发语言及人工智能工具的普及,使得越来越多的人会主动学习使用一些开发语言&…

Spring Boot应用部署 - JAR包部署

Spring Boot应用部署采用打包成JAR文件的方式,旨在利用其内置的嵌入式Tomcat或其他Servlet容器,简化传统Web应用部署流程。以下是详细的步骤和说明: 1. 使用Maven或Gradle进行打包 Maven 在Spring Boot项目中,确保pom.xml文件已…

面试题:如何实现一个RPC框架?

来源 滴滴二面 原问题 如何实现一个RPC框架? 考这个问题不是让你实现一个RPC框架,而是要看你对RPC框架的理解。 我的回答 我对RPC框架不太了解。 更好的答案 RPC概念 我们平时使用RPC框架时,可以在一个服务中,像调用本地方…