分布式协议与算法——CAP理论、ACID理论、BASE理论
CAP理论
CAP理论,对分布式系统的特性做了高度抽象,比如抽象成了一致性、可用性和分区容错性,并对特性间的冲突(也就是CAP不可能三角)做了总结。
CAP三指标
CAP理论对分布式系统的特性做了高度抽象,形成了三个指标:
- 一致性(Consistency)
- 可用性(Availability)
- 分区容错性(Partition Tolerance)
一致性:指的是客户端的每次读操作,不管访问哪个节点,要么读到的都是同一份最新写入的数据,要么读取失败。
可用性:指的是任何来自客户端的请求,不管访问哪个非故障节点,都能得到响应数据,但不保证是同一份最新数据。这个指标强调的是服务可用,但不保证数据正确。
分区容错性:指的是当节点间出现任意数量的消息丢失或高延迟的时候,系统仍然在继续工作。也就是说,分布式系统在告诉访问本系统的客户端:不管我的内部出现了什么样的数据同步问题,我会一直运行。这个指标强调的是集群对分区故障的容错能力。
在分布式系统中,分区容错性是必须要考虑的。
CAP不可能三角
CAP 不可能三角说的是对于一个分布式系统而言,一致性(Consistency)、可用性(Availability)、分区容错性(Partition Tolerance)3 个指标不可兼得,只能在 3 个指标中选择 2 个。

如何使用CAP理论
只要有网络交互就一定会有延迟和数据丢失,而这种状况必须接受,还必须保证系统不能挂掉。所以节点间的分区故障是必然发生的。也就是说,分区容错性(P)是前提,是必须要保证的。
那么剩下一致性(C)和可用性(A)可以选择了:要么选择一致性,保证数据正确;要么选择可用性,保证服务可用。
- 当选择了一致性(C)的时候,一定会读到最新的数据,不会读到旧数据,但如果因为消息丢失、延迟过高发生了网络分区,那么这个时候,当集群节点接收到来自客户端的读请求时,为了不破坏一致性,可能会因为无法响应最新数据,而返回出错信息。
- 当选择了可用性(A)的时候,系统将始终处理客户端的查询,返回特定信息,如果发生了网络分区,一些节点将无法返回最新的特定信息,它们将返回自己当前的相对新的信息。
许多人认为无论在什么情况下,分布式系统都只能在C和A中选择1个。其实在分布式系统正常运行时,就是说在不需要P时,C和A能够同事保证。只有当发生分区故障的时候,也就是说需要P时,才会在C和A之间做出选择。
小结
CA模型,在分布式系统中不存在。因为舍弃 P,意味着舍弃分布式系统,就比如单机版关系型数据库 MySQL,如果 MySQL 要考虑主备或集群部署时,它必须考虑 P。
CP模型,采用 CP 模型的分布式系统,舍弃了可用性,一定会读到最新数据,不会读到旧数据。一旦因为消息丢失、延迟过高发生了网络分区,就影响用户的体验和业务的可用性(比如基于 Raft 的强一致性系统,此时可能无法执行读操作和写操作)。典型的应用是 Etcd,Consul 和 Hbase。
AP模型,采用 AP 模型的分布式系统,舍弃了一致性,实现了服务的高可用。用户访问系统的时候,都能得到响应数据,不会出现响应错误,但会读到旧数据。典型应用就比如 Cassandra 和 DynamoDB。
在当前分布式系统开发中,延迟是非常重要的一个指标,比如,在 QQ 后台的名字路由系统中,通过延迟评估服务可用性,进行负载均衡和容灾;再比如,在 Hashicorp/Raft 实现中,通过延迟评估领导者节点的服务可用性,以及决定是否发起领导者选举。所以,在分布式系统的开发中,需要意识到延迟的重要性,能通过延迟来衡量服务的可用性。
ACID理论
ACID理论可以看成是对事务特性的抽象和总结,方便实现事务。可以理解为:如果实现了操作的ACID特性,那么就实现了事务。在单机上实现事务并不难,如可以通过锁、时间序列等机制保障操作的顺序执行,让系统实现ACID特性。但在分布式系统中比较困难,因为分布系统涉及多个节点间的操作。加锁、时间序列等机制,只能保证单个节点上的ACID特性,无法保证节点间操作的ACID特性。
通过分布式事务协议,如二阶段提交协议和**TCC(Try-Confirm-Cancel)**可以实现分布式系统上的ACID特性。
问题:
如何保证节点A、B、C执行分布式事务操作X,要么全部执行,要么全部不执行。
二阶段提交协议
二阶段提交协议(2pc),就是通过二阶段的协商来完成一个提交操作,具体的操作如下:
客户端发送消息给节点A,节点A收到消息后就扮演协调者(Coordinator)的身份,由节点A通信节点B和节点C,发起二阶段提交。

第一阶段为提交请求节点(又称投票阶段)。首先节点A向节点B和节点C发送消息:“能否执行操作X”,节点B和节点C判断 能否执行操作X,如果可以就预留一部分资源给操作X。最后将能否执行操作X发送给节点A,节点A收到全部的回复结果(包括自己的结果),这里假设全都是能够执行的回复。

第二阶段为提交执行阶段(又称完成阶段),也就是执行具体的操作了。首先节点A按照要么全部执行,要么全部放弃的原则,统计回复结果,由于所有的回复结果都是能够执行,所以节点A决定执行分布式事务操作X。然后通知节点B、节点C执行操作X。节点B和节点C在收到通知后,执行事务操作X。最后节点B和节点C将执行事务的结果返回给节点A。

在第一个阶段中,每个节点决定是放弃还是提交,一旦参与者决定提交事务,那么就不允许放弃事务。也就是说,在一个节点决定提交事务之前,它必须保证能够执行事务操作,即使出现故障或者中途被替换掉。
在第二个阶段中,事务的每个参与节点执行最终统一的决定,提交或者放弃事务。这个约定,实现了ACID中的原子性。
二阶段提交协议最早时用来实现数据库的分布式事务的,不过现在常用的协议是XA协议,该协议是基于二阶段提交协议提出的。不管是原始的二阶段提交协议,还是XA协议,都存在一些问题:
- 在提交请求阶段,需要预留资源,在资源预留期间,其他人不能操作。。
- 数据库是独立的系统。(数据库是独立的,也就是说数据库是独立的第三方软件,我们可以编程或修改业务代码,但很少会修改数据库核心代码,更不会根据业务需求修改实现不同的数据库代码逻辑。)
个人感觉2pc依赖每个数据库节点的事务。
TCC(Try-Confirm-Cancel)
TCC 是Try(预留)、Confirm(确认)、Cancel(撤销)3个操作的简称,它包含了预留、确认或撤销这2个阶段。
第一阶段为预留阶段。客户端通知节点A、节点B、节点C让它们预留执行操作X的相关资源,客户端实现确认操作(执行操作X)和撤销操作(取消执行操作X)。然后客户端收到节点A、节点B、节点C的预留答复,假设这里都是OK。

如果预留阶段的执行都没有问题,就进入确认阶段。客户端执行确认操作,通知节点A、节点B、节点C执行操作,客户端收到确认操作的响应后,完成分布式事务。

如果预留阶段出错,比如节点A无法执行操作X,那么就进入撤销阶段。客户端执行撤销操作,通知节点A、节点B、节点C取消执行操作X,客户端收到撤销操作的响应。

TCC本质上是补偿事务,它的核心思想是针对每个操作都要注册一个与其对应的确认操作和补偿操作(也就是撤销操作)。它是一个业务层面的协议,可以将TCC理解为编程模型,即TCC的三个操作都是在业务代码中编程实现的。为了实现一致性,确认操作和补偿操作必须是幂等的。这两个操作会失败重试。
TCC不依赖于数据库的事务(2pc应该是要依赖的),而是在业务中实现了分布式事务,这能减轻数据库的压力,但对业务代码的入侵性比较高,实现比较复杂。
ps:我感觉这点是与2pc不同的点吧,还有2pc是有一个节点作为协调者,而TCC是由客户端作为协调者。
小结
二阶段提交协议和TCC是实现分布式系统ACID特性的方法
- 二阶段提交协议,不仅仅是协议,也是一种非常经典的思想。二阶段提交在达成提交操作共识的算法中应用广泛,比如 XA 协议、TCC、Paxos、Raft 等。
- 幂等性,是指同一操作对同一系统的任意多次执行,所产生的影响均与一次执行的影响相同,不会因为多次执行而产生副作用。常见的实现方法有 Token、索引等。它的本质是通过唯一标识,标记同一操作的方式,来消除多次执行的副作用。
可以将 ACID 特性理解为 CAP 中一致性的边界,最强的一致性。根据 CAP 理论,如果在分布式系统中实现了一致性,可用性必然受到影响。比如,如果出现一个节点故障,则整个分布式事务的执行都是失败的。实际上,绝大部分场景对一致性要求没那么高,短暂的不一致是能接受的,另外,也基于可用性和并发性能的考虑,在开发实现分布式系统,如果不是必须,尽量不要实现事务,可以考虑采用最终一致性。
BASE理论
BASE 理论是 CAP 理论中的 AP 的延伸,是对互联网大规模分布式系统的实践总结,强调可用性。
BASE理论的核心是基本可用(Basically Available)和最终一致性(Eventually consistent)。还有一种过度状态—软状态(Soft state),软状态描述的是实现服务可用性的时候系统数据的一种过度状态,也就是说不通节点间,数据副本存在短暂的不一致。
实现可用的4种方式
- 流量削峰:例如12306订票系统,可以在不同的时间,出售不同区域的票,将访问请求错开,消弱请求峰值。
- 延迟响应:将购票请求在队列中进行排队,过段时间在进行处理。
- 体验降级:如使用小图片代替原始图片,通过降低图片的清晰度和大小,提升系统的处理能力。
- 过载保护:把接收到的请求放在指定的队列中排队处理,如果请求等待时间超时了(假设是 100ms),这个时候直接拒绝超时请求;再比如队列满了之后,就清除队列中一定数量的排队请求,保护系统不过载,实现系统的基本可用。
最终一致性
最终一致性是说,系统中所有的数据副本在经过一段时间的同步之后,最终能够达到一个一致的状态。在数据一致性上,存在一个短暂的延迟。
那么如何实现最终一致性? 首先确定它以什么为准,因为这是实现最终一致性的关键。一般来说,工程实践中有如下几种方式:
- 以最新写入的数据为准,比如 AP 模型的 KV 存储采用的就是这种方式(就是最新的数据);
- 以第一次写入的数据为准,如果你不希望存储的数据被更改,可以以它为准(就是一次写入后面不会修改了)。
常见的实现最终一致性的具体方式如下:
- 读时修复:在读取数据时,检测数据的不一致,进行修复。比如 Cassandra 的 Read Repair 实现,具体来说,在向 Cassandra 系统查询数据的时候,如果检测到不同节点的副本数据不一致,系统就自动修复数据。
- 写时修复:在写入数据,检测数据的不一致时,进行修复。比如 Cassandra 的 Hinted Handoff 实现。具体来说,Cassandra 集群的节点之间远程写数据的时候,如果写失败就将数据缓存下来,然后定时重传,修复数据的不一致性。
- 异步修复:这个是最常用的方式,通过定时检测副本数据的一致性,并修复(反熵的方式)。
写修复就是写的时候没有成功就将数据缓存下来,然后定时重传,保证数据写入成功。写修复不需要做数据一致性对比,性能消耗比较低,对系统运行影响不大。而读修复和异步修复需要做数据的一致性对比,性能消耗比较多。因此推荐写修复实现最终一致性。
小结
- BASE 理论是对 CAP 中一致性和可用性权衡的结果,它来源于对大规模互联网分布式系统实践的总结,是基于 CAP 定理逐步演化而来的。它的核心思想是,如果不是必须的话,不推荐实现事务或强一致性,鼓励可用性和性能优先,根据业务的场景特点,来实现非常弹性的基本可用,以及实现数据的最终一致性。
- BASE 理论主张通过牺牲部分功能的可用性,实现整体的基本可用,也就是说,通过服务降级的方式,努力保障极端情况下的系统可用性。
- ACID 理论是传统数据库常用的设计理念,追求强一致性模型。BASE 理论支持的是大型分布式系统,通过牺牲强一致性获得高可用性。BASE 理论在很大程度上,解决了事务型系统在性能、容错、可用性等方面痛点。另外我再多说一句,BASE 理论在 NoSQL 中应用广泛,是 NoSQL 系统设计的事实上的理论支撑。
参考
- 分布式协议与算法实战 学习笔记
相关文章:

分布式协议与算法——CAP理论、ACID理论、BASE理论
CAP理论 CAP理论,对分布式系统的特性做了高度抽象,比如抽象成了一致性、可用性和分区容错性,并对特性间的冲突(也就是CAP不可能三角)做了总结。 CAP三指标 CAP理论对分布式系统的特性做了高度抽象,形成了…...

接口测试 Jmeter 接口测试 —— 请求 Headers 与传参方式
一、 背景: 在使用 Jmeter 进行接口测试时,有些小伙伴不知道 Headers 和请求参数 (Parameters,Body Data) 的联系,本文主要讲 Content-Type 为 application/x-www-form-urlencoded 和 application/json 的场景。 1、使用 Parame…...

【redis】redis部署1主2从3哨兵demo搭建示例
redis版本为7,搭建的架构为1主2从3哨兵的架构。本文是对搭建的过程做一个回忆,过程可能遗漏了某些步骤,见谅。 首先,需要有一个已经安装了的redis。我们从redis源码目录中,找到一个redis.conf文件,这个文件…...

C++数据结构之平衡二叉搜索树(一)——AVL的实现(zig-zag/左右双旋/3+4重构)
目录 00.BBST——平衡二叉搜索树01.AVL树02.AVL的插入2.1单旋——zig 与 zag2.2插入节点后的单旋实例2.3手玩小样例2.4双旋实例2.5小结 03.AVL的删除3.1单旋删除3.2双旋删除3.3小结 04.34重构05.综合评价AVL5.1优点5.2缺点 00.BBST——平衡二叉搜索树 本文是介绍众多平衡二叉搜…...

免疫疗法勘察兵——DC细胞
DC细胞又叫树状细胞或者树突细胞,1869年由保罗兰格尔翰斯发现,一开始被误以为是神经细胞的一种,直到1973年皮肤科医师Inga Silberberg发现了他的免疫功能,同年,被拉尔夫斯坦曼和赞威尔A科恩两人正式命名为“dendritic…...

Django实现音乐网站 ⑷
使用Python Django框架制作一个音乐网站,在系列文章3的基础上继续开发, 本篇主要是后台歌曲类型表、歌单表模块功能开发。 目录 表结构设计 歌曲类型表结构 歌单表结构 创建表模型 创建表 后台注册表模型 引入表模型 后台自定义 总结 表结构设计…...

2023年华数杯数学建模C题思路 - 母亲身心健康对婴儿成长的影响
# 1 赛题 C 题 母亲身心健康对婴儿成长的影响 母亲是婴儿生命中最重要的人之一,她不仅为婴儿提供营养物质和身体保护, 还为婴儿提供情感支持和安全感。母亲心理健康状态的不良状况,如抑郁、焦虑、 压力等,可能会对婴儿的认知、情…...

openGauss学习笔记-30 openGauss 高级数据管理-别名
文章目录 openGauss学习笔记-30 openGauss 高级数据管理-别名30.1 语法格式30.1.1 列别名语法30.1.2 表别名语法 30.2 参数说明30.3 示例 openGauss学习笔记-30 openGauss 高级数据管理-别名 SQL可以重命名一张表或者一个字段的名称,这个名称为该表或该字段的别名。…...
C#实现多线程局域网扫描器的思路与具体代码
C#实现多线程局域网扫描器的思路与具体代码 思路: 获取局域网内所有 IP 地址遍历所有 IP 地址,使用 Ping 命令测试主机是否在线如果主机在线,则扫描主机上的所有端口,确定哪些端口是开放的输出扫描结果 在上述过程中࿰…...

Redis秒杀:一人一单问题及初步解决
优惠券秒杀一人一单 前言一、需求以及之前存在的问题二、增加一人一单逻辑1.初步代码2.封装一人一单逻辑3.控制锁的粒度 三、事务控制问题四、总结 前言 跟随黑马虎哥学习redis: 这是我认为b站上最好的redis教程,各方面讲解透彻,知识点覆盖…...

python 数据分析面试题:求分组排第n名的记录数据
近期面试遇到一个面试题,分享给大家。 文中会提供详细的解题思路以及问题延伸 一、面试题 面试题:输出各学科总分第一名的学员姓名、年龄、分数数据: class_a {name: [学员1, 学员2, 学员3, 学员4,学员5],age: [23, 24, 26, 27,25],course…...
eclipse常用快捷键
Eclipse常用快捷键 补全代码的声明:alt /快速修复: ctrl 1批量导包:ctrl shift o使用单行注释:ctrl /使用多行注释: ctrl shift /取消多行注释:ctrl shift \复制指定行的代码:ctrl alt down 或…...

什么是OCR?OCR技术详解
光学字符识别(Optical Character Recognition)简称为“OCR”。ORC是指对包含文本资料的图像文件进行分析识别处理,获取文字及版面信息的技术。 一般包括以下几个过程: 1.图像输入 针对不同格式的图像,有着不同的存储格式和压缩方式。目前&…...

【大模型】开源且可商用的大模型通义千问-7B(Qwen-7B)来了
【大模型】开源且可商用的大模型通义千问-7B(Qwen-7B)来了 新闻通义千问 - 7B 介绍评测表现快速使用环境要求安装相关的依赖库推荐安装flash-attention来提高你的运行效率以及降低显存占用使用 Transformers 运行模型使用 ModelScope 运行模型 量化长文本…...

SQL分类及通用语法数据类型
一、SQL分类 DDL: 数据定义语言,用来定义数据库对象(数据库、表、字段)DML: 数据操作语言,用来对数据库表中的数据进行增删改DQL: 数据查询语言,用来查询数据库中表的记录DCL: 数据控制语言,用来创建数据库…...

亿欧智库:2023中国功效型护肤产品成分解析研究报告(附下载
关于报告的所有内容,公众【营销人星球】获取下载查看 核心观点 消费端:“纯净美妆〞概念火热,消费驱动因素向成分来源硬核转变 新冠疫情过后,消费者对于生活健康:自然,可持续的关注度持续上升。在消费者…...
Kubernetes高可用集群二进制部署(一)主机准备和负载均衡器安装
Kubernetes概述 使用kubeadm快速部署一个k8s集群 Kubernetes高可用集群二进制部署(一)主机准备和负载均衡器安装 Kubernetes高可用集群二进制部署(二)ETCD集群部署 Kubernetes高可用集群二进制部署(三)部署…...

python与深度学习(十二):CNN和猫狗大战二
目录 1. 说明2. 猫狗大战的CNN模型测试2.1 导入相关库2.2 加载模型2.3 设置保存图片的路径2.4 加载图片2.5 图片预处理2.6 对图片进行预测2.7 显示图片 3. 完整代码和显示结果4. 多张图片进行测试的完整代码以及结果 1. 说明 本篇文章是对上篇文章猫狗大战训练的模型进行测试。…...

React(1)——快速入门
目录 一、React背景简介 ❤️ 官网和资料 📚 介绍描述 🐧 React的特点 🔨 React高效的原因 🙏🏻 二、React的基本使用 💻 三、React JSX(JSX:JavaScript XML)📦 …...

【论文】【生成对抗网络五】Wasserstein GAN (WGAN)
【题目、作者】: 紫色:要解决的问题或发现的问题 红色:重点内容 棕色:关联知识,名称 绿色:了解内容,说明内容 论文地址: 论文下载 本篇文章仅为原文翻译,仅作参考。…...
KubeSphere 容器平台高可用:环境搭建与可视化操作指南
Linux_k8s篇 欢迎来到Linux的世界,看笔记好好学多敲多打,每个人都是大神! 题目:KubeSphere 容器平台高可用:环境搭建与可视化操作指南 版本号: 1.0,0 作者: 老王要学习 日期: 2025.06.05 适用环境: Ubuntu22 文档说…...

日语AI面试高效通关秘籍:专业解读与青柚面试智能助攻
在如今就业市场竞争日益激烈的背景下,越来越多的求职者将目光投向了日本及中日双语岗位。但是,一场日语面试往往让许多人感到步履维艰。你是否也曾因为面试官抛出的“刁钻问题”而心生畏惧?面对生疏的日语交流环境,即便提前恶补了…...
Spring Boot 实现流式响应(兼容 2.7.x)
在实际开发中,我们可能会遇到一些流式数据处理的场景,比如接收来自上游接口的 Server-Sent Events(SSE) 或 流式 JSON 内容,并将其原样中转给前端页面或客户端。这种情况下,传统的 RestTemplate 缓存机制会…...
【Java学习笔记】Arrays类
Arrays 类 1. 导入包:import java.util.Arrays 2. 常用方法一览表 方法描述Arrays.toString()返回数组的字符串形式Arrays.sort()排序(自然排序和定制排序)Arrays.binarySearch()通过二分搜索法进行查找(前提:数组是…...
java调用dll出现unsatisfiedLinkError以及JNA和JNI的区别
UnsatisfiedLinkError 在对接硬件设备中,我们会遇到使用 java 调用 dll文件 的情况,此时大概率出现UnsatisfiedLinkError链接错误,原因可能有如下几种 类名错误包名错误方法名参数错误使用 JNI 协议调用,结果 dll 未实现 JNI 协…...

深入理解JavaScript设计模式之单例模式
目录 什么是单例模式为什么需要单例模式常见应用场景包括 单例模式实现透明单例模式实现不透明单例模式用代理实现单例模式javaScript中的单例模式使用命名空间使用闭包封装私有变量 惰性单例通用的惰性单例 结语 什么是单例模式 单例模式(Singleton Pattern&#…...
什么?连接服务器也能可视化显示界面?:基于X11 Forwarding + CentOS + MobaXterm实战指南
文章目录 什么是X11?环境准备实战步骤1️⃣ 服务器端配置(CentOS)2️⃣ 客户端配置(MobaXterm)3️⃣ 验证X11 Forwarding4️⃣ 运行自定义GUI程序(Python示例)5️⃣ 成功效果
Java面试专项一-准备篇
一、企业简历筛选规则 一般企业的简历筛选流程:首先由HR先筛选一部分简历后,在将简历给到对应的项目负责人后再进行下一步的操作。 HR如何筛选简历 例如:Boss直聘(招聘方平台) 直接按照条件进行筛选 例如:…...

OPENCV形态学基础之二腐蚀
一.腐蚀的原理 (图1) 数学表达式:dst(x,y) erode(src(x,y)) min(x,y)src(xx,yy) 腐蚀也是图像形态学的基本功能之一,腐蚀跟膨胀属于反向操作,膨胀是把图像图像变大,而腐蚀就是把图像变小。腐蚀后的图像变小变暗淡。 腐蚀…...

用机器学习破解新能源领域的“弃风”难题
音乐发烧友深有体会,玩音乐的本质就是玩电网。火电声音偏暖,水电偏冷,风电偏空旷。至于太阳能发的电,则略显朦胧和单薄。 不知你是否有感觉,近两年家里的音响声音越来越冷,听起来越来越单薄? —…...