Serverless 云服务产品因其简化云部署而越来越受无状态应用程序的欢迎。本文论证,如果 serverless 平台可以将函数包装在数据库事务中,它们也将非常适合数据库驱动的应用程序。这种事务性 serverless 平台有两个独特的优势:过去事件的时间旅行调试和具有精确一次语义的可靠程序执行。
Serverless 云平台,如 AWS (亚马逊网络服务) Lambda 和 Azure Functions,正变得越来越流行,用于构建各种生产应用程序,如网站前端、ML (机器学习) 管道和图像处理系统。这些平台通过管理应用程序部署,从根本上简化了开发。开发人员只需单击一个按钮即可部署函数,平台会自动托管这些函数,保证其可用性,并扩展它们以处理不断变化的负载。
Serverless 平台主要用于无状态操作,如图像大小调整或视频处理。在此,我们将论证它们也应该用于部署有状态应用程序,特别是数据库驱动的应用程序,其业务逻辑经常查询和更新事务性数据库,如 Postgres 或 MySQL。数据库驱动的应用程序在现代企业中无处不在;示例包括电子商务 Web 服务、银行系统和在线预订系统。它们主要在基于服务器的平台(如 Kubernetes)上运行。因此,它们为 serverless 产品提供了巨大的机会,包括大多数企业 API 的后端和现代 Web 的大部分。
为了使 serverless 适用于数据库驱动的应用程序,serverless 平台需要进行一项关键的补充:允许开发人员将函数作为数据库事务执行。图 1 显示了传统 serverless 平台与事务性 serverless 平台中实现的库存预订函数。checkInventory
和 updateInventory
函数执行 SQL 查询。在传统 serverless 平台中,如果函数访问数据库,开发人员必须获取数据库连接,手动开始事务,执行业务逻辑和 SQL 查询,然后最终提交事务(图 1a)。
相比之下,事务性 serverless 平台管理数据库连接:如果函数访问数据库,它会使用平台提供的连接,该连接自动将函数包装在事务中(图 1b)。构建此类平台的想法已在多个研究项目中进行探索——由这些作者1 和其他人3,4。
正如本文解释的那样,事务性 serverless 平台不仅对开发人员来说更方便,而且还可以为数据库驱动的应用程序提供超越传统 serverless 或基于服务器的系统的强大优势。
首先,事务性 serverless 平台使程序更易于调试。现代应用程序很难调试,因为它们在分布式环境中运行,频繁并发访问共享状态,因此错误通常涉及复杂的竞争条件,这些条件在开发环境中不易重现。在传统 serverless 平台中,重现错误尤其困难,因为它们的执行环境是瞬态的,仅存在于云中。然而,事务性 serverless 平台可以通过时间旅行简化调试。2 由于平台将函数包装在事务中以协调其状态访问,调试器可以利用事务日志“及时回溯”,并在本地重放任何过去的事务性函数执行。
其次,事务性 serverless 平台可以提供可靠的程序执行。编写可靠的数据库驱动的应用程序很困难,因为它们通常协调多个关键业务任务,其中任何一个都可能失败。在基于服务器的应用程序中,解决此问题很困难,因为开发人员必须手动跟踪每个请求的状态并恢复失败的请求。传统 serverless 平台通过自动重启任何失败的任务来简化此过程,但这可能会导致操作执行多次(例如,支付两次),从而产生问题。然而,如果函数是事务,平台可以在与其业务逻辑相同的事务中记录其成功或失败,从而保证每个函数执行一次且仅执行一次。
事务性 serverless 平台可以提供类似于当今 serverless 平台的编程模型,其中开发人员将程序编写为函数工作流。每个函数执行单个操作。工作流(以有向图或状态机的形式实现)编排许多函数。流行的 serverless 工作流编排器包括 AWS Step Functions 和 Azure Durable Functions。
事务性 serverless 平台的区别特征在于,所有访问应用程序数据库的函数都包装在 ACID(原子性、一致性、隔离性和持久性)数据库事务中,如图 1b 所示。这些函数必须是确定性的,并且在数据库之外没有副作用。不访问数据库的函数(例如,那些进行外部 API 调用的函数)的工作方式与它们在传统 serverless 平台中的工作方式相同。
作为本文的运行示例,图 2 显示了一个 serverless 结账服务工作流的图表,该工作流首先为订单中的所有商品预留库存,然后处理订单的付款,最后将订单标记为准备发货。每个步骤都在单独的函数中实现。“处理付款”之外的所有函数(它使用第三方支付提供商)都连接数据库并包装在事务中。如果任何步骤失败,工作流会运行回滚函数以撤消之前的操作(例如,如果付款失败,则返回预留的库存)。
事务性 serverless 平台启用的一项强大而独特的功能是时间旅行调试:让开发人员在本地开发环境中忠实地重放生产跟踪,以重现过去发生的错误。时间旅行调试对于数据库驱动的应用程序尤其有用,因为它们经常在分布式环境中运行,在这些环境中,错误表现为仅在高并发下发生的竞争条件,并且几乎不可能在本地重现。
例如,假设图 2 中的“预留库存”操作被拆分为两个单独的事务性函数,如图 3 所示,该图显示了“预留库存”操作的一个有缺陷的实现。此实现包含一个竞争条件,如果两个请求同时到达,两者都可以预留相同的商品,可能导致供应商出售超过其可用数量的商品。
调试此类问题很棘手,因为它们仅在具有特定输入的多个并发请求以特定方式与特定数据库状态交错时才会出现。为了在本地重现该错误,开发人员不仅必须确定哪些请求导致了该错误,还必须确定这些请求中不同操作交错的顺序以及使该错误成为可能的精确数据库状态。在传统平台中,跟踪执行顺序和重建数据库状态的成本非常高:请求在许多分布式服务器上的许多并行线程上并发执行,可能每秒修改数据库数千次。
相比之下,先前的研究2 表明,事务性 serverless 平台使忠实重放成为可能,因为每个函数都包装在隔离的、原子的和确定性的事务中。这使得时间旅行调试器成为可能,它可以分两步忠实地重放生产跟踪(包括竞争条件和并发错误)
1. 使用数据库事务日志,它可以重构应用程序数据库在跟踪的第一个请求时的状态。
2. 它可以本地执行跟踪中的每个请求在重构的数据库上,按照它们最初在应用程序数据库的事务日志中执行的顺序执行它们的事务性函数。
时间旅行调试器通过在受控本地环境中重现复杂的并发错误来改善开发人员的生活。例如,如果调试器在包含图 3 中描述的错误的跟踪上运行,它会在仅包含一个商品的数据库上执行两个检查事务,然后执行两个更新事务,从而超卖该商品并重现该错误。此过程如图 4 所示。
时间旅行调试器可以提供另一个强大的功能,称为回溯执行:在过去的事件上执行修改后的代码。对于给定的跟踪,调试器执行回溯执行的方式与忠实重放类似,但使用每个函数的更新后的实现而不是原始实现。回溯执行对于回归测试尤其有用:在旧的生产跟踪上运行新代码版本以验证它是否正确处理它们。例如,假设图 3 中的错误已通过将检查和更新函数组合到一个事务性函数中来修复。时间旅行调试器可以通过重新执行原始跟踪,但在原始检查和更新的位置运行组合函数来追溯测试此修复。如图 5 所示,这验证了该修复消除了错误。
事务性 serverless 平台的另一个关键优势是可靠的程序执行。许多数据库驱动的应用程序必须协调多个关键业务任务,其中任何一个都可能失败。例如,图 2 中的结账工作流为每个订单执行三个任务:(1)预留其库存;(2)处理其付款;以及(3)将其标记为准备发货。为了可靠地执行,此类应用程序不仅必须处理这些任务中任何一个的失败,还必须从服务器崩溃等中断中恢复。具体而言,它们必须具有两个属性
• 程序运行至完成。 如果程序开始执行,则必须继续,通过任何中断进行恢复,直到达到最终的成功或失败状态。例如,如果在处理付款后结账服务中断,它必须恢复并标记订单为已发货(如果付款成功)或取消订单并返回预留的库存(如果付款失败)。
• 操作精确执行一次。 在执行程序时,其每个操作必须执行一次且仅执行一次。例如,如果您在中断后恢复结账服务,则不能天真地重新发送付款请求;否则,客户可能会支付两次。您必须改为确定原始付款请求的状态(是否已发送,如果已发送,则是否成功或失败),并相应地恢复。
在传统的基于服务器的应用程序中手动获得这些属性很困难。一种方法是将应用程序编写为状态机,该状态机在每次操作后将其状态检查点保存到持久性存储。如果程序中断,则从上次检查点保存的状态恢复执行。为了确保精确一次执行,使所有操作都具有幂等性,以便可以在恢复期间安全地重新执行它们。虽然这种方法有效,但它既繁琐又容易出错,并且需要仔细的程序设计。
现有的 serverless 平台简化了编写运行至完成的程序,但不提供精确一次执行。这自然而然地源于 serverless 编程模型。如果程序编写为函数工作流,则工作流编排器可以在每次函数执行后记录工作流的状态,然后在工作流执行中断时从上次记录的状态恢复。因此,serverless 函数编排器(如 AWS Step Functions 和 Azure Durable Functions)运行工作流直至完成,重新启动每个函数,直到它成功或达到预定义的失败状态。
持久工作流引擎(如 Temporal)为基于服务器的程序提供类似的保证,前提是它们被编写为操作工作流。然而,由于编排器将函数视为黑盒,因此它们无法提供精确一次语义,而是重新启动每个函数直到它成功。如果函数在完成之后但在记录其成功之前崩溃,则会重新执行它,从而可能损坏数据。
正如先前的工作1,4 所表明的那样,事务性 serverless 平台不仅可以保证程序运行至完成,还可以保证事务性操作精确执行一次。由于平台将函数包装在事务中,因此它可以在与函数相同的事务中记录事务性函数的成功或失败。因此,如果函数完成,其成功或失败始终记录在数据库中,而如果函数失败,其所有操作都将由数据库回滚。因此,平台知道永远不要重新执行具有记录结果的函数,但始终可以安全地重新执行没有记录结果的函数。
数据库驱动的应用程序是 serverless 计算令人兴奋的新前沿。通过紧密集成应用程序执行和数据管理,事务性 serverless 平台实现了许多在现有 serverless 平台或基于服务器的部署中不可能实现的新功能。
本文解释了这样的平台如何有益于应用程序的可调试性和可靠性。
它的其他好处包括
• 可观察性,因为平台可以跟踪每个数据项的完整历史记录(来源),包括所有修改过它的函数。
• 安全性,因为平台可以实时监控数据上的所有操作。
• 性能,因为平台可以将事务性函数与应用程序数据库并置。
我们期待未来在这个领域的工作。
1. Kraft, P., Li, Q., Kaffes, K., Skiadopoulos, A., Kumar, D., Cho, D., Li, J., Redmond, R., Weckwerth, N., Xia, B., Bailis, P., Cafarella, M., Graefe, G., Kepner, J., Kozyrakis, C., Stonebraker, M., Suresh, L., Yu, X., Zaharia, M. 2023. Apiary: a DBMS-integrated transactional function-as-a-service framework. arXiv:2208.13068; https://arxiv.org/abs/2208.13068.
2. Li, Q., Kraft, P., Cafarella, M., Demiralp, C., Graefe, G., Kozyrakis, C., Stonebraker, M., Suresh, L., Yu, X., Zaharia, M. 2023. R3: record-replay-retroaction for database-backed applications. Proceedings of the VLDB Endowment 16(11), 3085–3097; https://dl.acm.org/doi/10.14778/3611479.3611510.
3. Wu, C., Sreekanti, V., Hellerstein, J. M. 2020. Transactional causal consistency for serverless computing. In Proceedings of the 2020 SIGMOD International Conference on Management of Data, 83–97; https://dl.acm.org/doi/10.1145/3318464.3389710.
4. Zhang, H., Cardoza, A., Chen, P. B., Angel, S., Liu, V. 2020. Fault-tolerant and transactional stateful serverless workflows. In 14th Usenix Symposium on Operating Systems Design and Implementation, 1187–1204; https://www.usenix.org/conference/osdi20/presentation/zhang-haoran.
Qian Li 是 DBOS, Inc. 的联合创始人。她获得了斯坦福大学计算机科学博士学位,导师是 Christos Kozyrakis。她的研究兴趣包括 serverless、数据库和云资源管理。
Peter Kraft 是 DBOS, Inc. 的联合创始人。他获得了斯坦福大学计算机科学博士学位,在那里他与 Matei Zaharia 和 Peter Bailis 共事。他的兴趣在于数据库、云基础设施和分布式系统。
版权 © 2024 由所有者/作者持有。出版权已授权给 。
最初发表于 Queue vol. 22, no. 3—
在 数字图书馆 中评论本文
Pat Helland - 任何其他名称的身份
新的新兴系统和协议既收紧又放宽了我们对身份的概念,这很好!它们使完成工作变得更容易。REST、IoT、大数据和机器学习都围绕着有意保持灵活且有时模棱两可的身份概念。身份概念是我们分布式系统的基本机制的基础,包括互换性、幂等性和不变性。
Raymond Blum, Betsy Beyer - 实现数字永久性
当今的信息时代正在为世界依赖的数据创造新的用途和新的管理方式。世界正在远离熟悉的物理人工制品,转向更接近其本质信息的新表示方式。我们需要流程来确保知识的完整性和可访问性,以保证历史将被知晓和真实。
Graham Cormode - 数据草图
您是否曾经感到被源源不断的信息淹没?似乎不断涌入的新电子邮件和短信要求您持续关注,还有电话要接听、文章要阅读以及敲门声要应答。将这些碎片拼凑在一起以跟踪重要事项可能是一个真正的挑战。为了应对这一挑战,流数据处理模型越来越受欢迎。其目标不再是捕获、存储和索引每一分钟的事件,而是快速处理每个观察结果,以便创建当前状态的摘要。
Heinrich Hartmann - 工程师统计学
现代 IT 系统从网络设备、操作系统、应用程序和其他组件收集越来越多的数据。需要分析这些数据,以得出有关用户体验和业务绩效的重要信息。例如,需要检测故障,需要测量服务质量,并且需要预测未来几天和几个月的资源使用情况。