5.1 数据一致性
引入事务的目的,是为了保证数据的一致性(Consistency)。
这里的一致性指的是,对数据有特定的预期状态,任何数据更改操作必须满足这些状态约束(或者恒等条件)。例如,处理一个转账业务,其中 A 向 B 转账 ¥50 元。在事务的支持下,无论是在转账前、转账过程中、还是转账完成后,A 和 B 的总金额始终保持不变。这意味着数据在整个过程中都保持一致,符合业务约束。
想要达成数据的一致性,需要 3 个方面的努力:
- 原子性(Atomic):通常,原子是指不可分解为更小粒度的东西。这里原子性描述的是,客户端发起一个包含多个写操作请求时可能发生的情况,例如只完成了一部分写入操作,系统出现故障了(进程崩溃、网络中断、节点宕机);把多个写入操作纳入到一个原子事务,万一出现上述故障导致无法完成最终提交时,则事务中止,且数据库必须丢弃或者撤销那些局部修改。
- 隔离性(Isolation):同时运行的事务不应该互相干扰。例如,如果某个事物进行多次写入,则另一个事物观察到的应该是其全部完成的结果,而不应该看到中间部分结果。隔离性可以防止多个事务并发执行时,由于交叉执行而导致数据的不一致。
- 持久性(Durability):事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。对于单节点的数据库,持久性意味着数据已经被写入存储设备,如硬盘或者 SSD。对于分布式数据库,持久性则意味着数据已成功复制到多个节点。为了实现持久性保证,数据库必须等到复制完成才能报告事务成功提交。
这也就是常说的事务的“ACID 特性”。值得一提的是,对于一致性而言,更多的是指应用层的属性。应用程序借助数据库提供的原子性、隔离性和持久性,以达到一致性。也就是说,A、I、D 是手段,C(Consistency)是 3 者协作的目标,弄到一块完全是为了读起来更顺口。
当事务中修改的操作局限在本地时,一致性通过编码实现起来水到渠成。但倘若事务修改的对象影响涉及外部,如跨越不同的微服务、跨越不同的数据源,甚至跨越多个数据中心时,一致性问题通常很难再使用 A、I、D 来解决。但是,一致性又是分布式系统中必然会遇到且必须要解决的问题。这种情况下,我们需要转变观念,将一致性视为一个多元问题,而非简单的“是或否”的二元问题。根据不同场景的需求,对一致性的强度进行分级讨论,在确保代价可承受的前提下,最大程度地保障系统的一致性。
一致性的强弱程度关乎系统设计权衡。由此,事务处理从一个具体操作上的“编程问题”转变成一个需要全局权衡的“架构问题”。人们在探索这些架构的设计时产生了诸多思路和理论,这其中最为出名的是一致性与可用性的权衡定理 —— CAP 定理。
总字数:937字