热门标签 | HotTags
当前位置:  开发笔记 > 后端 > 正文

双重写入:如何解决微服务分布式系统中数据不一致?Thorben

由于许多新应用程序是作为微服务系统构建的,因此双重写入已成为一个普遍的问题。它们是导致数据不一致的最常见原因之一。更糟的是,许多开发人员甚至都不知道双重写入是什么。什么是双重写入?



由于许多新应用程序是作为微服务系统构建的,因此双重写入已成为一个普遍的问题。它们是导致数据不一致的最常见原因之一。更糟的是,许多开发人员甚至都不知道双重写入是什么。

什么是双重写入?
双重写入描述了您在两个个系统(例如数据库和Apache Kafka)中更改数据时的情况,而没有额外的层来确保两个服务上的数据一致性。


只要两个操作都成功,一切就OK了。即使第一笔交易失败,也还是可以的。但是,如果您成功提交了第一笔交易而第二笔交易失败,则说明您遇到了问题。您的系统现在处于不一致状态,没有容易修复的方法。

分布式事务不再是一种选择
过去,当我们构建整体/.单体/Monolith时,我们使用分布式事务来避免这种情况。分布式事务使用两阶段提交协议。它将事务的提交过程分为两个步骤,并确保所有系统的ACID原则。
但是,如果我们要构建微服务系统,则不会使用分布式事务。这些交易需要锁,并且无法很好地扩展。他们还需要所有涉及的系统同时启动和运行。

那你该怎么办呢?

3个无效的“解决方案”
当我在会议演讲中或在一个研讨会上与与会者讨论此主题时,我经常听到以下3条建议之一:

  1. 是的,我们知道此问题,我们没有解决方案。但这还不错。到目前为止,什么都没有发生。让我们保持原样。
  2. 让我们将与Apache Kafka的交互移动到提交后监听器。
  3. 在提交数据库事务之前,让我们将事件写入Kafka中的主题。

好吧,很明显,建议1的风险很大。它可能在大多数时间都有效。但是迟早,您将在服务存储的数据之间创建越来越多的不一致之处。
因此,让我们集中讨论选项2和3。

2. 在提交后监听器中发布事件
在提交后监听器中发布事件是一种非常流行的方法。它确保仅在数据库事务成功时才发布事件。但是,很难解决Kafka崩溃或任何其他原因阻止您发布事件的情况。
您已经提交了数据库事务。因此,您无法轻松地还原这些更改。当您尝试在Kafka中发布事件时,其他事务可能已经使用并修改了该数据。
您可能会尝试将故障保留在数据库中,并运行常规的清理作业以尝试恢复失败的事件。这可能看起来像是一个合理的解决方案,但是它有一些缺陷:
  1. 仅当您可以将失败的事件保留在数据库中时,它才有效。如果数据库事务失败,或者您的应用程序或数据库崩溃,然后才能存储有关失败事件的信息,则将丢失它。
  2. 仅当事件本身没有引起问题时,它才起作用。
  3. 如果在清除作业恢复失败的事件之前,另一个操作为该业务对象创建了一个事件,则事件将混乱。

这些似乎是假设的情况,但这就是我们正在准备的事情。本地事务,分布式事务和确保最终一致性的方法的主要思想是,绝对要确保您不会造成任何(永久)不一致。
提交后侦听器无法确保这一点。因此,让我们看一下其他选项。

3. 在提交数据库事务之前发布事件
在讨论了为何提交后监听器不起作用之后,通常会建议使用这种方法。如果在提交之后发布事件会导致问题,您只需在提交事务之前发布它,对吗?
好吧,不……让我解释一下……
如果您无法发布事件,则在提交事务之前发布事件使您可以回滚事务。那就对了。
但是,如果数据库事务失败,该怎么办?
您的操作可能违反唯一约束,或者同一数据库记录上可能有2个并发更新。提交期间将检查所有数据库约束,并且不能确保它们都不会失败。数据库事务也彼此隔离,因此如果不使用锁,就无法阻止并发更新。但这带来了新的可伸缩性问题。简而言之,您的数据库事务可能会失败,并且您无能为力,或者对此无能为力。
如果发生这种情况,则您的活动已经发布。其他微服务可能已经观察到它并触发了一些业务逻辑。您无法撤回活动。
如前所述,撤消操作失败的原因相同。您也许可以构建一个大多数情况下都可以使用的解决方案。但是您无法创建绝对安全的东西。

如何避免双重写入?
您可以选择几种方法来避免双重写入。但是您需要知道,如果不使用分布式事务,则只能构建最终一致的系统。
总体思路是将流程分为多个步骤。这些步骤中的每个步骤仅适用于一个数据存储,例如数据库或Apache Kafka。这使您能够使用本地事务,所涉及系统之间的异步通信以及异步的,可能无限的重试机制。
如果您只想在服务之间复制数据或通知其他服务已发生事件,则可以将发件箱模式与Debezium等变更数据捕获实现一起使用。我在以下文章中详细解释了这种方法:


  • 使用Hibernate实现发件箱模式
  • 使用Debezium用CDC实现发件箱模式

而且,如果您需要实施涉及多个服务的一致的写入操作,则可以使用SAGA模式。我将在以下文章之一中对其进行详细说明。

结论
双重写入常常被低估,许多开发人员甚至都不知道潜在的数据不一致。
如本文所述,在没有分布式事务或确保最终一致性的算法的情况下,写入2个或更多系统可能会导致数据不一致。如果使用多个本地事务,则无法处理所有错误情况。
避免这种情况的唯一方法是将通信分为多个步骤,并且在每个步骤中仅写入一个外部系统。SAGA模式和变更数据捕获实现(例如Debezium)使用这种方法来确保对多个系统的一致写入操作或将事件发送到Apache Kafka。


 

推荐阅读
  • 电商高并发解决方案详解
    本文以京东为例,详细探讨了电商中常见的高并发解决方案,包括多级缓存和Nginx限流技术,旨在帮助读者更好地理解和应用这些技术。 ... [详细]
  • 流处理中的计数挑战与解决方案
    本文探讨了在流处理中进行计数的各种技术和挑战,并基于作者在2016年圣何塞举行的Hadoop World大会上的演讲进行了深入分析。文章不仅介绍了传统批处理和Lambda架构的局限性,还详细探讨了流处理架构的优势及其在现代大数据应用中的重要作用。 ... [详细]
  • 本文总结了一次针对大厂Java研发岗位的面试经历,探讨了面试中常见的问题及其背后的原因,并分享了一些实用的面试准备资料。 ... [详细]
  • 第二章:Kafka基础入门与核心概念解析
    本章节主要介绍了Kafka的基本概念及其核心特性。Kafka是一种分布式消息发布和订阅系统,以其卓越的性能和高吞吐量而著称。最初,Kafka被设计用于LinkedIn的活动流和运营数据处理,旨在高效地管理和传输大规模的数据流。这些数据主要包括用户活动记录、系统日志和其他实时信息。通过深入解析Kafka的设计原理和应用场景,读者将能够更好地理解其在现代大数据架构中的重要地位。 ... [详细]
  • Uniswap 与 MoonPay 合作,引入法币交易功能。本文探讨这一合作对用户进入加密货币领域的安全性及便利性的影响。 ... [详细]
  • 从理想主义者的内心深处萌发的技术信仰,推动了云原生技术在全球范围内的快速发展。本文将带你深入了解阿里巴巴在开源领域的贡献与成就。 ... [详细]
  • 本文探讨了在Windows系统中运行Apache服务器时频繁出现崩溃的问题,并提供了多种可能的解决方案和建议。错误日志显示多个子进程因达到最大请求限制而退出。 ... [详细]
  • 本文详细探讨了在Web开发中常见的UTF-8编码问题及其解决方案,包括HTML页面、PHP脚本、MySQL数据库以及JavaScript和Flash应用中的乱码问题。 ... [详细]
  • Ubuntu 环境下配置 LAMP 服务器
    本文详细介绍了如何在 Ubuntu 系统上安装和配置 LAMP(Linux、Apache、MySQL 和 PHP)服务器。包括 Apache 的安装、PHP 的配置以及 MySQL 数据库的设置,确保读者能够顺利搭建完整的 Web 开发环境。 ... [详细]
  • mybatis 详解(七)一对一、一对多、多对多
    mybatis详解(七)------一 ... [详细]
  • 2023年最新指南:如何在PHP中屏蔽警告和错误
    本文详细介绍了如何在PHP中屏蔽警告和错误,包括多种方法和最佳实践,帮助开发者提升代码质量和安全性。 ... [详细]
  • RocketMQ在秒杀时的应用
    目录一、RocketMQ是什么二、broker和nameserver2.1Broker2.2NameServer三、MQ在秒杀场景下的应用3.1利用MQ进行异步操作3. ... [详细]
  • 在当今的软件开发领域,分布式技术已成为程序员不可或缺的核心技能之一,尤其在面试中更是考察的重点。无论是小微企业还是大型企业,掌握分布式技术对于提升工作效率和解决实际问题都至关重要。本周的Java架构师实战训练营中,我们深入探讨了Kafka这一高效的分布式消息系统,它不仅支持发布订阅模式,还能在高并发场景下保持高性能和高可靠性。通过实际案例和代码演练,学员们对Kafka的应用有了更加深刻的理解。 ... [详细]
  • 本文探讨了 Kafka 集群的高效部署与优化策略。首先介绍了 Kafka 的下载与安装步骤,包括从官方网站获取最新版本的压缩包并进行解压。随后详细讨论了集群配置的最佳实践,涵盖节点选择、网络优化和性能调优等方面,旨在提升系统的稳定性和处理能力。此外,还提供了常见的故障排查方法和监控方案,帮助运维人员更好地管理和维护 Kafka 集群。 ... [详细]
  • 技术日志:深入探讨Spark Streaming与Spark SQL的融合应用
    技术日志:深入探讨Spark Streaming与Spark SQL的融合应用 ... [详细]
author-avatar
mobiledu2502909383
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有