《解读NoSQL》——2.5 比较ACID和BASE——两种可靠的数据库事务方法

简介: 让我们从一个简单的银行业务案例来展现一个可靠的事务。如今,许多人都有两个银行账户:储蓄账户和支票账户。如果你想将一些资金从一个账户转账到另一个账户,银行在网站上会有转账页面,进行如图2-7所示的一个资金转账流程

本节书摘来自异步社区出版社《解读NoSQL》一书中的第2章,第2.5节,作者: 【美】Dan McCreary(丹•麦克雷) , Ann Kelly(安•凯利),更多章节内容可以访问云栖社区“异步社区”公众号查看。

2.5 比较ACID和BASE——两种可靠的数据库事务方法

兼顾性能和一致性的事务控制在分布式计算环境下是很重要的。通常会在两种事务控制模型中选择其一使用:ACID用于RDBMS,BASE用在很多NoSQL系统。即使数据库事务只有很少一部分需要事务完整性,但了解RDBMS和NoSQL系统能够采用这些事务控制策略也是很重要的。这两种模型的区别在于应用开发人员所付出的努力和事务控制所发生的位置(层级)。

让我们从一个简单的银行业务案例来展现一个可靠的事务。如今,许多人都有两个银行账户:储蓄账户和支票账户。如果你想将一些资金从一个账户转账到另一个账户,银行在网站上会有转账页面,进行如图2-7所示的一个资金转账流程。
image

图2-7 这一系列原子步骤将资金从一个账户转账到另一个账户。第一步从储蓄账户扣除所要转账的金额。第二步将相等的转账金额增加到支票账户。由于事务应该是可靠的,所以所有步骤要么都执行要么都不执行。在事务步骤之间,任何显示账户总额由于交易金额而减少的报表都不应该被允许运行

当点击了网页上的转账按钮,两个独立的操作必须共同执行。首先从储蓄账户中扣除转账金额,然后再加到支票账户中。事务管理是确保这两个操作作为一个整体一起发生或者一起不发生的过程。如果计算机在第一个步骤完成后而第二个步骤还没开始时崩溃了,你要损失1 000美元,你当然会对银行产生极大不满。

传统的商业数据库都以在金融事务方面的稳定和可靠而闻名。这不仅因为它们已经存在了相当长的时间,且一直不断地进行着优化,还因为它使得程序员通过在事务开始和结束的地方进行声明就可以很容易地保障关键事务的可靠性。这些声明被称作启动事务(OPEN TRANSACTION)和结束事务(END TRANSACTION)。通过添加它们,开发者能够获得高可靠的事务支持。如果两个原子操作中的一个没有完成,那么所有操作都会被回滚至它们最初的状态。

系统同样确保了不会有任何账户报表在操作进行到一半时生成。如果你在事务过程中执行生成账户余额报表,它将不会显示先有1 000数额的减少然后再增加1 000。如果报表在事务的第一个步骤进行时开始生成,它将会被阻塞,直到整个事务完成。

在传统的RDBMS中,事务管理的复杂性由数据库层负责解决。应用开发者只需要处理在整个事务失败时,如何通知正确的组件或者不停重试直到事务完成。应用开发者并不需要知道如何撤销一个事务的各种部分,因为这已经成为了数据库内建的一部分。

由于可靠的事务对于大多数应用系统是很重要的,接下来的两小节将深入研究RDBMS的事务控制——ACID和NoSQL系统的事务控制——BASE。

2.5.1 RDBMS的事务控制——ACID

RDBMS的事务控制通过原子性、一致性、隔离性和持久性(ACID)属性来保证事务是可靠的。接下来将对每一个属性进行定义。

原子性——在银行交易的例子中,我们提到过从储蓄账户到支票账户的现金转移的过程要么一起发生要么都不发生。如果用技术术语来形容就是原子性,它来自于希腊语的“不可分”。如果系统声明支持原子性事务,那么它必须考虑所有失败的情况:磁盘故障、网络故障、硬件故障或者单纯的程序错误。即使是在单个CPU之上测试原子性事务也是很困难的。

一致性——在银行交易的例子中,我们在两个相关账户之间进行资金转移,而总账户余额从未改变,这是一致性的原则。那意味着数据库不能在支票账户余额增加之前显示储蓄账户余额减少。数据库负责在原子操作持续的时间内阻塞所有报表。当数据库基于同样的记录同时运行很多原子性事务和报表时,会影响系统的速度。

隔离性——隔离性指的是其他事务对该事务的每一部分的执行都不知情。例如,增加金额的事务并不知道从账户扣除金额的事务。

持久性——持久性指的是这样一个事实,一旦事务的所有方面完成,它将是永久性的。一旦转账的按钮被选中,你将可以消费你的支票账户中的资金。如果银行系统在那天晚上崩溃了,他们需要用备份磁带恢复数据库,那么必须用某些方法确保转账记录也被恢复。这通常意味着银行必须在一个独立的计算机系统中保留一份事务日志,当备份恢复完成后,根据事务日志重新执行一遍所有事务。

如果你认为处理这些规则的软件一定很复杂,那么你是正确的。确实非常复杂,这也是关系型数据库非常昂贵的原因之一。如果你自己正在编写一个数据库,那么有些必需的软件模块的数量很容易增至2倍或是3倍。这也是新数据库产品经常在第一个发布版中不支持数据库级别的事务管理的原因,而是在产品成熟后才会加入。

许多RDBMS将事务发生的范围限制在单个CPU之内。如果考虑这种情况:你的储蓄账户的信息存储在纽约的一台计算机里,你的支票账户信息存储在旧金山的一台计算机里,那么复杂程度将会增加,因为这种情况有更多的失效点并且需要阻塞的基于这两个系统的报表系统的数量也会增加。

尽管支持ACID的事务很复杂,但还是有一些著名的、公认的策略来实现。它们都是基于锁定资源,并预留出额外副本的资源,然后执行事务,如果一切都没问题,再释放资源。如果事务的任何一部分出错,有争议的资源必须回到它的初始状态。设计上的挑战在于搭建支持这些事务的系统,使得应用可以个更容易地使用事务并且保证数据库的运行速度和响应能力。

ACID系统关注数据的一致性和完整性,且高于其他考量。暂时阻塞报表的机制是为了确保系统返回可靠准确的信息的一种合理的妥协。ACID系统可以说是悲观的,因为它们必须考虑计算环境里所有可能的失效模式。有时ACID系统似乎服从墨菲定律——会出错的事总会出错——并且必须仔细测试保证事务完整性。

ACID系统高度关注数据完整性,NoSQL却是基于BASE准则考虑一系列稍有不同的约束。如果在等待另一个事务完成前阻塞事务对你来说是不可接受的妥协,会怎么样?如果你有一个接受客户订单的网站,有时ACID系统不一定是你想要的。

2.5.2 非RDBMS的事务控制——BASE

假如你的网站是运行在遍布世界各地的计算机上,会怎样?芝加哥的计算机负责管理库存,而负责保存产品照片的图像数据库在弗吉尼亚,计算税收的程序在西雅图运行,账户系统在亚特兰大。如果一旦其中一个站点宕机会怎么样?你是否应该告诉客户等你在20分钟内解决问题后再回来?除非你是想将客户拱手相让给竞争对手。使用ACID系统处理到达的每一个订单现实吗?让我们看看另一种选择。

使用“购物车”和“结账台”概念的网站对于事务处理有不同的侧重。在几分钟内报表不一致与无法下订单相比是不那么重要的,因为如果阻塞一个订单,就损失了一个客户。这种情况下,可以使用BASE来替代ACID。下面是BASE的一些概念。

基本可用是指允许系统暂时不一致,这样事务就容易管理。在BASE系统中,信息和服务能力是“基本可用的”。

软状态是指为了降低消耗的资源,可以暂时允许一些不准确的地方和数据的变换。

最终一致性意味着在最后,当所有服务逻辑执行完成后,系统最后将回到一个一致的状态。
与RDBMS关注一致性不同,BASE系统关注可用性。BASE系统显著的特点是它们的首要目标是要保证在短时间内,即使有不同步的风险,也要允许新数据能够被存储。NoSQL系统放宽了规则并允许即使不是所有数据库都是同步的,也能运行报表。BASE系统不被认为是悲观的,因为它们并不会关心某个过程背后的细节。它们是乐观的,因为它们假设最后所有系统都会同步而变得一致。

BASE系统倾向于更加简单和迅速,因为它们不必编写处理锁定和释放资源的代码。它们的任务是保证流程运转并稍后处理出错的部分。BASE系统非常适合支持网上商店,填满购物车和下订单才是它们的主要优先功能。

在NoSQL运动之前,大多数数据库专家认为ACID系统是唯一能够商用的事务类型。NoSQL系统是高度去中心化的,并且ACID提供的保障有时不是必须的,所以NoSQL采用了BASE和一些更为宽松的方法。图2-8显示了一个准确的、有点幽默的ACID和BASE哲学之间的对比。
image

图2-8 ACID与BASE——了解其中的利弊。该图比较了应用于严格的金融账户规则的传统RDBMS的ACID事务与NoSQL系统更加宽松的BASE方法。当要求所有报表必须始终保持一致性和可信性,RDBMS ACID系统是理想的选择。当把永远不阻塞写事务作为高优先级任务时,NoSQLBASE系统是合适的选择。业务需求将决定是传统的RDBMS还是NoSQL系统适合你的应用

最后还要提醒读者:ACID和BASE并没有一个严格界限,它们取决与组织和系统决定在哪里和如何架构这个系统的场景。它们可能允许在某些关键领域采取严格的ACID事务,其他领域标准稍微放松一些。一些数据库系统通过改变配置文件或者使用不同的API提供了双重选择。系统管理员和应用开发者可以一起在考虑了业务的需要之后,实现正确的选项。

当你为了处理海量数据而进行扩展并将系统架构从集中式迁移到分布式系统时,事务是重要的。但是有时你管理的数据超过了当前系统能够管理的规模,那就需要采取数据库分片来保证新系统运行并减少宕机时间。

相关文章
|
1月前
|
SQL 缓存 PHP
PHP技术探究:优化数据库查询效率的实用方法
本文将深入探讨PHP中优化数据库查询效率的实用方法,包括索引优化、SQL语句优化以及缓存机制的应用。通过合理的优化策略和技巧,可以显著提升系统性能,提高用户体验,是PHP开发者不容忽视的重要议题。
|
1月前
|
存储 缓存 NoSQL
利用Redis List实现数据库分页快速查询的有效方法
利用Redis List实现数据库分页快速查询的有效方法
|
1月前
|
SQL 关系型数据库 数据库
事务隔离级别:保障数据库并发事务的一致性与性能
事务隔离级别:保障数据库并发事务的一致性与性能
|
1月前
|
算法 大数据 数据库
数据库事务:保障数据一致性的基石
数据库事务:保障数据一致性的基石
|
3月前
|
设计模式 NoSQL Java
常用的设计模式以及操作Redis、MySQL数据库、各种MQ、数据类型转换的方法
常用的设计模式以及操作Redis、MySQL数据库、各种MQ、数据类型转换的方法
|
4月前
|
存储 SQL 关系型数据库
认识数据库中的事务机制
认识数据库中的事务机制
19 0
|
1月前
|
SQL 关系型数据库 MySQL
【MySQL】— —熟练掌握用SQL语句实现数据库和基本表的创建。熟练掌握MySQL的安装、客户端登录方法;熟练掌握MySQL的编码、数据类型等基础知识;掌握实体完整性的定义和维护方法、掌握参照完整性
【MySQL】— —熟练掌握用SQL语句实现数据库和基本表的创建。熟练掌握MySQL的安装、客户端登录方法;熟练掌握MySQL的编码、数据类型等基础知识;掌握实体完整性的定义和维护方法、掌握参照完整性
101 1
|
4月前
|
SQL 监控 druid
p6spy【SpringBoot集成】使用p6spy-spring-boot-starter集成p6spy监控数据库(配置方法举例)
p6spy【SpringBoot集成】使用p6spy-spring-boot-starter集成p6spy监控数据库(配置方法举例)
189 0
|
1月前
|
SQL 关系型数据库 MySQL
【MySQL 数据库】4、MySQL 事务学习
【MySQL 数据库】4、MySQL 事务学习
44 0
|
3月前
|
SQL Java 关系型数据库
数据库事务
数据库事务
25 0

热门文章

最新文章