ACID事务不仅仅适用于银行——Vitess的解决方案
传统的“从账户A向账户B转账”的例子已经不能满足当今新兴应用场景的需要了。Vitess为这一问题提供了答案。
还记得2000年代初的《办公室疯云》(Office Space)那个年代吗?Java还是新鲜事物,Usenet被认为是社交媒体,而应用程序还在使用Sun公司专属硬件搭配Oracle数据库。随后,随着科技泡沫的破裂,企业开始转向使用普通的廉价硬件和开源数据库。在许多情况下,这些企业选择了MySQL作为数据库。整体成本有所降低,但也不得不放弃某些功能。由于硬件和软件的限制,许多环境中的MySQL配置方式导致系统崩溃时可能会丢失数据。
数据库系统传统上通过ACID(原子性、一致性、隔离性和持久性)为应用程序提供一系列的保证。无论是在正常运行中还是在发生故障时,应用程序都应该能够依赖这些保证。
其中,持久性尤为重要,它意味着:当系统确认事务完成(在数据库中称为提交)时,即使发生系统崩溃或断电,该事务也应该能够永久存活并不会丢失。
持久性真的重要吗?
当企业开始使用运行在廉价硬件上的MySQL时,它们并未总是配置以提供完整的ACID保证。同时,类似MongoDB的NoSQL系统逐渐流行开来,而这些系统最初甚至不提供ACID事务或持久性保证。作为回报,企业获得了更好的性能。这种操作方式更多地将修改缓冲到内存中,然后批量访问存储设备。
可扩展性(即“网络级扩展”)成为了优先级。在复杂系统中,故障总是难以避免,但提供在故障情况下的正确性却退居其次。
对此,我对此有着深刻印象,尤其是在YouTube早期开发时。当时团队中的许多人曾在PayPal工作过,在放宽对持久性要求时,常听到的口头禅是“没关系,这又不是钱。”然而这种心态最终因盈利化的需求而改变,其中计数(例如观看次数)与盈利挂钩变得更加重要。
在当今时代,比金融交易更能体现持久性需求的例子并不难寻找。
适合当代应用的更好的例子
传统的ACID示例通常讲述,当从账户A取出20美元并存入账户B时,可能出现的故障包括:金钱丢失、两个账户同时被记入金额、或者交易被确认成功但随后又被撤销。
在今天的应用程序中,以下情境更具代表性:
当你使用类似Slack的协作工具时,你可能决定创建一个私密频道供几位同事加入。随后你发现自己添加了一个错误的成员,并试图将其移除。当你移除此成员时系统返回更新成功的确认。这一更改会通过数据库服务器更新一个记录。如果服务器在两秒后崩溃,你的预期是:此成员已经被成功移除,并且不会再看到该频道内容。
同样地,当我向同事发送消息时,我期望消息已经发出。对于由于系统故障导致消息显示为已发送但实际上未被接收,这种情况我是无法接受的。
(注:Slack实际上避免了这类问题,因为其采用Vitess进行存储并实现了高效率扩展。)
上述问题是异步故障引发的结果。问题根源在于:数据库服务器向应用程序确认操作成功,应用程序继而通知用户成功,但随后数据库服务器没能兑现承诺。
Vitess解决方案
Vitess是一个基于MySQL的开源数据库扩展系统,最初由YouTube开发以实现大规模扩展。如今,它已成为CNCF毕业的项目(与Kubernetes、Prometheus等项目并列)。
Vitess通过两种方法避免上述异步故障:
- 首先,它确保更改被安全地存储在本地磁盘上,包括重做日志(Redo Log)和二进制日志(Binary Log)。MySQL较新的版本(5.7+)默认会这样做,而Vitess确保它支持的所有版本都实现这一点。
- 其次,Vitess使用半同步复制(Semi-Synchronous Replication)。该技术确保更改不仅被应用到本地数据库服务器,还至少有另一个备援服务器接收并持久保存了该更改。
“半同步复制”在持久性保证和性能之间实现了良好的平衡。相比之下,一些新系统使用法定人数(Quorum)模型来解决这一问题,即对多数节点接受修改进行确认后才视事务成功。然而,当系统规模扩大(节点增多)时,性能开销也随之增加,从而导致性能下降。
Vitess另一大优势在于并非每个副本(Replica)均需属于半同步组。您可以设计失败隔离区,例如至少一个副本位于不同的可用区或数据中心中,确保满足条件才视操作成功。
多年来,Vitess一直是YouTube、Slack、Square Cash、Pinterest、京东、Hubspot等公司的记录系统。截至今日,我们并未听说这些公司因使用Vitess导致数据丢失的案例。
结论:构建不会丢失数据的系统
现代应用早已深深融入我们的生活。在生活的越来越多方面依赖应用程序时,用户对持久性和一致性的期望也随之提升。2000年代初的各种捷径帮助我们在技术尚未成熟时实现了系统扩展。而如今拥有了先进技术,我们应当构建即使在日常故障中也不会丢失数据,且在灾难性故障中数据丢失概率极低的系统。
关注公众号:程序新视界,一个让你软实力、硬技术同步提升的平台
除非注明,否则均为程序新视界原创文章,转载必须以链接形式标明本文链接