分布式事务处理中的幂等性
事务是指以全有或全无的方式执行的一系列操作。所有操作必须全部成功完成,否则在每个操作中所作的所有更改都会被撤消。
以数据库为列,事物包含四个特性(ACID)
- 原子性(Atomicity):操作这些指令时,要么全部执行成功,要么全部不执行。只要其中一个指令执行失败,所有的指令都执行失败,数据进行回滚,回到执行指令前的数据状态。
- 一致性(Consistency):事务的执行使数据从一个状态转换为另一个状态,但是对于整个数据的完整性保持稳定。
- 隔离性(Isolation):隔离性是当多个用户并发访问数据库时,比如操作同一张表时,数据库为每一个用户开启的事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离。即要达到这么一种效果:对于任意两个并发的事务T1和T2,在事务T1看来,T2要么在T1开始之前就已经结束,要么在T1结束之后才开始,这样每个事务都感觉不到有其他事务在并发地执行。
- 持久性(Durability):当事务正确完成后,它对于数据的改变是永久性的。
而在分布式系统中,你不能指望ACID事务。因为在分布式系统中会对数据库进行分区,这里所说的分区指的是物理分区,分区之后可能不同的库就处于不同的服务器上了,这个时候单个数据库的ACID已经不能适应这种情况了,而在这种ACID的集群环境下,再想保证集群的ACID几乎是很难达到,或者即使能达到那么效率和性能会大幅下降。
在没有ACID的情况下解决数据一致性的常见技巧是使用补偿。这种方法与ACID事务不同,你可以具有不一致的中间状态。在业务处理中通常可以忍受这些暂时的不一致,只要能确保最终清理它们并使系统恢复到一致状态。这称为最终一致性,这是分布式系统中的一个重要概念。
最终的一致性通常会产生更好的性能,更简单的操作和更好的可伸缩性,同时帮助程序员理解更复杂的数据模型。
在实现最终一致性时会出现消息重复发送问题。实际应用情况是,在分布式系统中确切地保证消息传递是不可能的。实现一次准确的消息传递完全基于消息生成者从消息使用者那里接收到确认消息。但是,ACK本身是不可靠的,因为它也将通过网络传播。在处理消息后,由于网络问题或消费者崩溃,很可能会丢失ACK。
任何通过网络进行通信,都可能会出现三种故障情形:
- 该请求尚未到达服务提供商
- 请求已到达服务提供商,但在处理期间出现异常
- 服务提供程序处理了请求,但响应丢失了
那么如何才能实现准确的消息传递?它的答案是幂等性!你必须使你的消费者操作具有幂等性。幂等性就是用户对于同一操作发起的一次请求或者多次请求的结果是一致的,不会因为多次点击而产生了副作用。举个最简单的例子,用户购买商品后支付,支付扣款成功,但是返回结果的时候网络异常,此时钱已经扣了,用户再次点击按钮,此时不应该进行第二次扣款。
添加幂等性处理方法:
- 唯一标识。你可以生成唯一标识符并将其添加到业务中。这样,如果在服务提供端存储该ID,则可以轻松发现重复调用。
- 利用工作流引擎,比如Apache ActiveMQ可以在生产者向代理发送消息时过滤掉重复项,代理索引可以跟踪和识别重复项并将其丢弃。
- 请求哈希。如果你使用消息传递,则可以通过存储消息的哈希值来执行相同的操作。
上一篇: 什么是接口的幂等性,如何确保它的幂等性?
下一篇: 如何确保接口的幂等性?
推荐阅读
-
如何确保接口的幂等性?
-
分布式事务处理中的幂等性
-
什么是接口的幂等性,如何确保它的幂等性?
-
高并发性的接口幂等性解决方案
-
编程中的幂等性 - HTTP 幂等性
-
重构 API 的幂等性详解
-
更深入地了解幂等性和幂等性问题与 Restful 风格 API 的详细关系
-
一篇关于界面幂等性架构设计解决方案的文章
-
请求幂等性的 java 实现 java 中的幂等性
-
什么是数据库事物?为什么需要数据库事物,事物有哪些特征?事物的隔离级别是什么?-1.什么是数据库事务? 1.事务是作为一个逻辑单元执行的一系列操作。一个逻辑工作单元必须具备四个属性,即ACID(原子性、一致性、隔离性和持久性)属性,只有这样才能成为事务: 原子性 2.事务必须是一个原子工作单元;它的数据修改要么全部执行,要么全部不执行。 一致性 3.事务完成时,所有数据必须保持一致。在相关数据库中,所有规则都必须适用于事务的修改,以保持所有数据的完整性。事务结束时,所有内部数据结构(如 B 树索引或双向链接表)必须正确无误。 隔离 4.并发事务的修改必须与其他并发事务的修改隔离。一个事务会在另一个并发事务修改之前或之后查看某一状态下的数据,而不会查看中间状态下的数据。这就是所谓的可序列化,因为它允许重新加载起始数据和重放一系列事务,从而使数据最终处于与原始事务执行时相同的状态。 持久性 5.事务完成后,它对系统的影响是永久性的。即使在系统发生故障的情况下,修改也会保留。 2. 为什么需要数据库事物,事物有哪些特征? 事物对数据库的作用是对数据进行一系列操作,要么全部成功,要么全部失败,防止出现中间状态,确保数据库中的数据始终处于正确、和谐的状态。 特征:原子性、一致性、隔离性、持久性,以及其他特征 原子性(Atomicity):所有操作在事务开始后,要么全部做完,要么全部不做,不可能停滞在中间环节。事务执行过程中出现错误时,会回滚到事务开始前的状态,所有操作就像没有发生一样。也就是说,事务是一个不可分割的整体,就像化学中的原子一样,是物质的基本单位。 一致性(Consistency):在事务开始之前和结束之后,数据库的完整性约束都没有被破坏。例如,如果 A 转钱给 B,A 不可能扣除这笔钱,但 B 却没有收到这笔钱。 隔离:在同一时间内,只允许一个事务请求相同的数据,不同事务之间没有干扰。例如,甲正在从一张银行卡上取款,在甲取款过程结束之前,乙不能向这张卡转账。 持久性(耐用性):事务完成后,事务对数据库的所有更新都将保存到数据库中,无法回滚 3.事务的隔离级别有哪些? 数据库事务有四种隔离级别,从低到高分别是未提交读取(Read uncommitted)、已提交读取(Read committed)、可重复读取(Repeatable read)、可序列化(Serializable)。此外,事务的并发操作中可能会出现脏读、不可重复读、幽灵读等情况。事务并发问题 脏读:事务 A 读取事务 B 更新的数据,然后事务 B 回滚操作,那么事务 A 读取的数据就是脏数据。 不可重复读取:事务 A 多次读取同一数据,事务 B 在事务 A 多次读取期间更新并提交数据,导致事务 A 多次读取同一数据时结果不一致。 幻影读取:系统管理员 A 将数据库中所有学生的具体分数改为 ABCDE 等级,但系统管理员 B 在此时插入了具体分数的记录,当系统管理员 A 更改结束后发现仍有一条记录未被更改,仿佛发生了幻觉,这称为幻影读取。 小结:不可重复读和幻读容易混淆,不可重复读侧重于修改,幻读侧重于增删。解决不可重复读问题只需锁定满足条件的行,解决幻读问题则需要锁定表 MySQL 事务隔离级别