微服务架构中的数据一致性

在微服务中,一个逻辑上原子操作可以经常跨越多个微服务 。即使是单片系统也可能使用多个数据库或消息传递解决方案 。使用多个独立的数据存储解决方案,如果其中一个分布式流程参与者出现故障 , 我们就会面临数据不一致的风险 - 例如在未下订单的情况下向客户收费或未通知客户订单成功 。在本文中,我想分享一些我为使微服务之间的数据最终保持一致而学到的技术 。
为什么实现这一目标如此具有挑战性?只要我们有多个存储数据的地方(不在单个数据库中) , 就不能自动解决一致性问题,工程师在设计系统时需要注意一致性 。目前,在我看来 , 业界还没有一个广为人知的解决方案,可以在多个不同的数据源中自动更新数据 - 我们可能不应该等待很快就能获得一个 。
以自动且无障碍的方式解决该问题的一种尝试是实现两阶段提交(2PC)模式的XA协议 。但在现代高规模应用中(特别是在云环境中) , 2PC似乎表现不佳 。为了消除2PC的缺点 , 我们必须交易ACID for BASE并根据要求以不同方式覆盖一致性问题 。
Saga模式在多个微服务中处理一致性问题的最着名的方法是Saga模式 。 您可以将Sagas视为多个事务的应用程序级分布式协调 。根据用例和要求,您可以优化自己的Saga实施 。相反,XA协议试图涵盖所有场景 。Saga模式也不是新的 。它在过去已知并用于ESB和SOA体系结构中 。最后,它成功地转变为微服务世界 。跨越多个服务的每个原子业务操作可能包含技术级别的多个事务 。Saga Pattern的关键思想是能够回滚其中一个单独的交易 。众所周知,开箱即用的已经提交的单个事务无法进行回滚 。但这是通过引入补偿操作来实现的 - 通过引入“取消”操作 。

微服务架构中的数据一致性

文章插图
图片
除了取消之外,您还应该考虑使您的服务具有幂等性,以便在出现故障时重试或重新启动某些操作 。应监控故障,并应积极主动地应对故障 。
对账如果在进程的中间负责调用补偿操作的系统崩溃或重新启动,该怎么办?在这种情况下,用户可能会收到错误消息,并且应该触发补偿逻辑,或者 - 当处理异步用户请求时,应该恢复执行逻辑 。
微服务架构中的数据一致性

文章插图
图片
要查找崩溃的事务并恢复操作或应用补偿,我们需要协调来自多个服务的数据 。对账
是在金融领域工作的工程师所熟悉的技术 。你有没有想过银行如何确保你的资金转移不会丢失,或者两个不同的银行之间如何汇款?快速回答是对账 。
微服务架构中的数据一致性

文章插图
图片
在会计中 , 对账是确保两组记录(通常是两个账户的余额)达成一致的过程 。对帐用于确保离开帐户的资金与实际支出的资金相匹配 。这是通过确保在特定会计期间结束时余额匹配来完成的 。- Jean Scheid , “了解资产负债表账户调节”,Bright Hub,2011年4月8日
回到微服务,使用相同的原则,我们可以在一些动作触发器上协调来自多个服务的数据 。当检测到故障时,可以按计划或由监控系统触发操作 。最简单的方法是运行逐记录比较 。可以通过比较聚合值来优化该过程 。在这种情况下,其中一个系统将成为每条记录的真实来源 。
事件簿想象一下多步骤交易 。如何在对帐期间确定哪些事务可能已失败以及哪些步骤失败?一种解决方案是检查每个事务的状态 。在某些情况下 , 此功能不可用(想象一下发送电子邮件或生成其他类型消息的无状态邮件服务) 。在其他一些情况下 , 您可能希望立即了解事务状态 , 尤其是在具有许多步骤的复杂方案中 。例如 , 预订航班,酒店和转机的多步订单 。
微服务架构中的数据一致性

文章插图
图片
复杂的分布式流程在这些情况下 , 事件日志可以提供帮助 。记录是一种简单但功能强大的技术 。许多分布式系统依赖于日志 。“预写日志记录”是数据库在内部实现事务行为或维护副本之间一致性的方式 。相同的技术可以应用于微服务设计 。在进行实际数据更改之前,服务会写入有关其进行更改的意图的日志条目 。实际上 , 事件日志可以是协调服务所拥有的数据库中的表或集合 。


推荐阅读