凤凰架构 - 事务处理
2025-2-1
| 2025-2-1
字数 1317阅读时长 4 分钟
status
type
date
slug
summary
tags
category
icon
password
事务处理几乎在每一个信息系统中都会涉及,它存在的意义是为了保证系统中所有的数据都是符合期望的,且相互关联的数据之间不会产生矛盾,即数据状态的一致性Consistency)。
 
按照数据库的经典理论,要达成这个目标,需要三方面共同努力来保障。
  • 原子性Atomic):在同一项业务处理过程中,事务保证了对多个数据的修改,要么同时成功,要么同时被撤销。
  • 隔离性Isolation):在不同的业务处理过程中,事务保证了各自业务正在读、写的数据互相独立,不会彼此影响。
  • 持久性Durability):事务应当保证所有成功被提交的数据修改都能够正确地被持久化,不丢失数据。
 
以上四种属性即事务的“ACID”特性,但笔者对这种说法其实不是太认同,因为这四种特性并不正交,A、I、D 是手段,C 是目的,前者是因,后者是果,弄到一块去完全是为了拼凑个单词缩写。
 
事务的概念虽然最初起源于数据库系统,但今天已经有所延伸,而不再局限于数据库本身了,所有需要保证数据一致性的应用场景,包括但不限于数据库、事务内存、缓存、消息队列、分布式存储,等等,都有可能会用到事务,后文里笔者会使用“数据源”来泛指所有这些场景中提供与存储数据的逻辑设备,但是上述场景所说的事务和一致性含义可能并不完全一致,说明如下。
  • 当一个服务只使用一个数据源时,通过 A、I、D 来获得一致性是最经典的做法,也是相对容易的。此时,多个并发事务所读写的数据能够被数据源感知是否存在冲突,并发事务的读写在时间线上的最终顺序是由数据源来确定的,这种事务间一致性被称为“内部一致性”。
  • 当一个服务使用到多个不同的数据源,甚至多个不同服务同时涉及多个不同的数据源时,问题就变得相对困难了许多。此时,并发执行甚至是先后执行的多个事务,在时间线上的顺序并不由任何一个数据源来决定,这种涉及多个数据源的事务间一致性被称为“外部一致性”。
外部一致性问题通常很难再使用 A、I、D 来解决,因为这样需要付出很大乃至不切实际的代价;但是外部一致性又是分布式系统中必然会遇到且必须要解决的问题,为此我们要转变观念,将一致性从“是或否”的二元属性转变为可以按不同强度分开讨论的多元属性,在确保代价可承受的前提下获得强度尽可能高的一致性保障,也正因如此,事务处理才从一个具体操作上的“编程问题”上升成一个需要全局权衡的“架构问题”。
 
 

本地事务

本地事务是最基础的一种事务解决方案,只适用于单个服务使用单个数据源的场景。
从应用角度看,它是直接依赖于数据源本身提供的事务能力来工作的,在程序代码层面,最多只能对事务接口做一层标准化的包装(如 JDBC 接口),并不能深入参与到事务的运作过程当中,事务的开启、终止、提交、回滚、嵌套、设置隔离级别,乃至与应用代码贴近的事务传播方式,全部都要依赖底层数据源的支持才能工作,这一点与后续介绍的 XA、TCC、SAGA 等主要靠应用程序代码来实现的事务有着十分明显的区别。举个例子,假设你的代码调用了 JDBC 中的Transaction::rollback()方法,方法的成功执行也并不一定代表事务就已经被成功回滚,如果数据表采用的引擎是MyISAM,那rollback()方法便是一项没有意义的空操作。因此,我们要想深入地讨论本地事务,便不得不越过应用代码的层次,去了解一些数据库本身的事务实现原理,弄明白传统数据库管理系统是如何通过 ACID 来实现事务的。
 
  • 架构
  • Do Show 訪談|黃子華运动后及时学习
    Loading...
    目录