小白都能看懂的分布式事务与2PC

2024-01-20 23:32

本文主要是介绍小白都能看懂的分布式事务与2PC,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

2PC通信原理

  • 分布式事务的原子性
  • 什么是2PC
  • 2PC提交事务的过程
  • 2PC的全局提交规则
  • 2PC通信架构
    • 集中式2PC通信架构
    • 分层2PC通信架构
    • 线性2PC通信架构
  • 故障恢复
    • 站点故障
    • 报文丢失
  • 总结

分布式事务的原子性

一提到到事务,一般就会想到它的ACID特性,其中A(atomic)其实就是指事务的原子性。那么什么是原子性呢,简单来说原子性就是要求事务只有两个状态:

  1. 一是成功,也就是所有操作全部成功
  2. 二是失败,任何操作没有被执行,即使过程中已经执行了部分操作,也要保证回滚这些操作。

其实要做到原子性并不容易,因为多数情况下事务是由多个操作构成的序列。而分布式事务原子性的表现与普通的事务原子性一致。分布式事务要涉及多个物理节点,而且还增加了网络这个不确定因素,使得要满足分布式事务的原子性问题更加复杂。
那么,如何协调内部的多项操作从而对外表现出统一的成功或者失败呢?这需要一系列的算法或者协议来保证。下面我们就来说一下最重要的2PC协议。

什么是2PC

2PC(Two-phase Commitment Protocal)。作为数据库领域最常用的协议,首次提出是Jim Gray在1977年发表的一份文稿中提出的。但是,2PC在工程中的应用其实还要早几年。
2PC可以应用在分布式事务,保证了分布式事务提交的原子性,并在不损坏日志的情况下.实现快速故障恢复,提高分布式数据库系统的可靠性。
在分布式事务中,把分布式事务的某一个代理(根代理)指定为协调者(coodinator),所有其他代理称为参与者(Participants)。只有协调者才有掌握提交或撤销事务的决定权,而其他参与者各自负责在其本地数据库中执行写操作,并向协调者提出撤销或提交子事务的意向。
其实在生活中2PC的例子有很多。下面通过一个例子来讲解2PC的原理。某班要组织一个同学聚会活动,该活动的前提条件是所有参与者(participant)同意才能举行,任意一个人不同意则取消该活动。那么该怎么举办这次活动呢?
第一阶段(phase1)
组织者(coordinator)打电话给所有参与者(participant),同时告知他们参与者列表(请注意这个参与者列表非常重要)。
proposal:提出周六2pm-5pm举办活动
vote:参与者需要投票给组织者accept 或者reject
block:如果参与者都accept,则组织者锁住2pm-5pm的时间,不再接受其它请求。
第二阶段(phase2)
commit:如果所有参与者都同意,则组织者(coordinator)通知所有参与者commit,否则通知abort,组织者解除绑定

这种提交方式也是有失败的可能性的,失败情况总结起来分为以下两种:
1.参与者失败(Participant failure):
任一参与者无响应,coordinator直接执行abort
2.(协调者失败)Coordinator failure:
Takeover: 如果participant一段时间没收到cooridnator确认(commit/abort),则认为coordinator不在了。这时候可切换自动成为Coordinator备份(watchdog)
Query: watchdog根据phase 1接收到的参与者列表发起query
Vote: 所有participant回复vote结果给watchdog, accept or reject。
Commit: 如果所有都同意,则commit, 否则abort。

2PC提交事务的过程

所以通过上节的例子,总结起来2PC把事务的提交过程分为两个阶段
1.第一阶段是表决阶段,目的是形成一个共同的决定。
2.第二阶段是执行阶段,目的是实现这个决定。根据协调者的指令。参与者或者提交事务,或者撤销事务,并给协调者发送确认消息。此时,协调者在日志中写入一条事务结束记录并终止事务。
协调者与参与者两阶段提交过程如下图所示
在这里插入图片描述

2PC的全局提交规则

1.只要有一个参与者撤销事务,协调者就必须做出全局撤销决定。
2.只有所有参与者都同意提交事务,协调者才能做出全局提交决定。
:协调者和参与者可能进入某些相互等待对方发送消息的状态。为了确保它们能够从这些状态中退出并终止,要使用定时器。
每个进程进入一个状态时都要设置定时器。如果所期待的消息在定时器超时之前没有到来,定时器向进程报警,进程于是调用它自己的超时协议。

2PC通信架构

集中式2PC通信架构

集中式两阶段提交协议,通信只发生在协调者和参与者之间,参与者之间不交换消息。
在这里插入图片描述

分层2PC通信架构

在协调者和参与者之间的通信不用直接广播的方法进行,而是使报文在树中上下传播
在这里插入图片描述

线性2PC通信架构

在线性两阶段提交协议中,参与者之间可以相互通信。为了通信,系统中的站点之间要进行排序。假设参与事务执行的站点之间的顺序是1到N,协调者就是序列中的第一个。
实现两阶段提交协议时,在第一阶段使用了向前通信方式,从协调者(No.1)到N;在第二阶段使用了向后通信方式,即从N到协调者。
线性2PC产生较少的消息.但是不提供任何并行。因此,它增加了响应时间,降低了性能。
在这里插入图片描述

故障恢复

故障类型一般分为站点故障、报文丢失两种。下面来讲讲该如何恢复

站点故障

1.一参与者在把就绪记录写入运行记录以前出现故障。在这种情况下,协调者超时机制满期,它将采取撤消的决定。所有的参与者都撤销它们的子事务。当发生该故障的参与者恢复时,重启动过程简单地撤销该事务即可.不需要过问其它站点的情况。
2.一参与者在把就绪记录写入运行记录以后发生故障。在这种情况下,其它参与者的站点终止该事务(提交或撤消)。当故障站点恢复时,重启动过程不得不询问协调者或别的某个参与者关于该事务的结果(提交或撤消),然后执行相应的动作(提交或撤消)。这种情况下需要访问远程的恢复信息。
3.协调者在把预备记录写入运行记录以后,而在写入global-commit或global-abort记录以前发生故障。这种情况下所有已经回答READY的参与者必须等待协调者恢复。协调者的重启动过程从头开始恢复提交协议,从预备记录(在运行记录中)读取参与者的标识,再次把PREPARE(预备)报文发送给它们。每个就绪的参与者必须要识别出该新的PREPARE报文是前一个PREPARE的重复报文。
4.协调者在运行中写入global-commit或global-abort记录以后而在写入完成记录以前发生故障。这种情况下,协调者在重启动时必须再次给所有参与者发送其决定,未曾收到此命令的所有参与者不得不等待到协调者恢复为止。和以前一样,参与者不应因收到该命令报文两次而受到影响。
5.协调者在运行记录中写入完成以后发生故障。这种情况下,该事物已经结束,在重启动时不需任何动作。

报文丢失

1.来自一个参与者的回答报文(READY或ABORT)被丢失。在这种情况下,协调者的超时满期,整个事务被撤销。要注意,只由协调者来发现这种故障,而从协调者的观点来看,它完全好像是一参与者的故障。但是.从参与者的观点来看情况就不同了,该参与者并不认为自己有故障,因而不会执行重启动过程。
2.丢失一个PREPARE报文。这种情况下该参与者仍停在等待状态。因为协调者并没有收到回答,所以其全局结果和前一种情况相同。
3.丢失一个命令报文(commit或abort)。参与者对此命令处于不肯定状态。在参与者中引入超时机制就可简单地消除这个问题;从回答起在超时后仍末收到任何报文的话,就发送—请求再发送该命令。
4.丢失一个ACK报文。协调者对参与者有无收到该报文处于不肯定状态。可以在协调者中引入超时机制就可简单地消除这个问题;如果从发出命令起到超时后仍未受到任何ACK报文,协调者就再次发送该命令。在参与者站点处理这种情况的最好办法是再次发送ACK报文,即使该子事务在那期间已经完成并不再活动也要重发。

总结

事实上,大多数分布式数据库都是在2PC协议基础上改进来保证分布式事务的原子性。下一篇将介绍两个有代表性的改进模型,它们分别来自两大阵营NewSQL和PGXC。

这篇关于小白都能看懂的分布式事务与2PC的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/627700

相关文章

MySQL 事务的概念及ACID属性和使用详解

《MySQL事务的概念及ACID属性和使用详解》MySQL通过多线程实现存储工作,因此在并发访问场景中,事务确保了数据操作的一致性和可靠性,下面通过本文给大家介绍MySQL事务的概念及ACID属性和... 目录一、什么是事务二、事务的属性及使用2.1 事务的 ACID 属性2.2 为什么存在事务2.3 事务

Golang实现Redis分布式锁(Lua脚本+可重入+自动续期)

《Golang实现Redis分布式锁(Lua脚本+可重入+自动续期)》本文主要介绍了Golang分布式锁实现,采用Redis+Lua脚本确保原子性,持可重入和自动续期,用于防止超卖及重复下单,具有一定... 目录1 概念应用场景分布式锁必备特性2 思路分析宕机与过期防止误删keyLua保证原子性可重入锁自动

基于MongoDB实现文件的分布式存储

《基于MongoDB实现文件的分布式存储》分布式文件存储的方案有很多,今天分享一个基于mongodb数据库来实现文件的存储,mongodb支持分布式部署,以此来实现文件的分布式存储,需要的朋友可以参考... 目录一、引言二、GridFS 原理剖析三、Spring Boot 集成 GridFS3.1 添加依赖

Spring Boot 事务详解(事务传播行为、事务属性)

《SpringBoot事务详解(事务传播行为、事务属性)》SpringBoot提供了强大的事务管理功能,通过@Transactional注解可以方便地配置事务的传播行为和属性,本文将详细介绍Spr... 目录Spring Boot 事务详解引言声明式事务管理示例编程式事务管理示例事务传播行为1. REQUI

MySQL中的事务隔离级别详解

《MySQL中的事务隔离级别详解》在MySQL中,事务(Transaction)是一个执行单元,它要么完全执行,要么完全回滚,以保证数据的完整性和一致性,下面给大家介绍MySQL中的事务隔离级别详解,... 目录一、事务并发问题二、mysql 事务隔离级别1. READ UNCOMMITTED(读未提交)2

如何合理使用Spring的事务方式

《如何合理使用Spring的事务方式》:本文主要介绍如何合理使用Spring的事务方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、介绍1.1、底层构造1.1.事务管理器1.2.事务定义信息1.3.事务状态1.4.联系1.2、特点1.3、原理2. Sprin

MySQL中的两阶段提交详解(2PC)

《MySQL中的两阶段提交详解(2PC)》:本文主要介绍MySQL中的两阶段提交(2PC),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录引言两阶段提交过程sync_binlog配置innodb_flush_log_at_trx_commit配置总结引言在Inn

Docker安装MySQL镜像的详细步骤(适合新手小白)

《Docker安装MySQL镜像的详细步骤(适合新手小白)》本文详细介绍了如何在Ubuntu环境下使用Docker安装MySQL5.7版本,包括从官网拉取镜像、配置MySQL容器、设置权限及内网部署,... 目录前言安装1.访问docker镜像仓库官网2.找到对应的版本,复制右侧的命令即可3.查看镜像4.启

Redis实现分布式锁全解析之从原理到实践过程

《Redis实现分布式锁全解析之从原理到实践过程》:本文主要介绍Redis实现分布式锁全解析之从原理到实践过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、背景介绍二、解决方案(一)使用 SETNX 命令(二)设置锁的过期时间(三)解决锁的误删问题(四)Re

Gradle下如何搭建SpringCloud分布式环境

《Gradle下如何搭建SpringCloud分布式环境》:本文主要介绍Gradle下如何搭建SpringCloud分布式环境问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地... 目录Gradle下搭建SpringCloud分布式环境1.idea配置好gradle2.创建一个空的gr