数据库新增幂等操作_使用数据库唯一键实现事务幂等性

幂等性

概念

在分布式系统中,幂等性是一致性方面的一个重要概念。

幂等(idempotent、idempotence)是一个数学与计算机学概念,常见于抽象代数中。

在编程中一个幂等操作的特点是其任意多次执行所产生的影响均与一次执行的影响相同。

所谓“影响相同”,不是要求返回值完全相同,而且是指后续多余的调用对系统的数据一致性不造成破坏。对于写入类操作,如果第一次写入是成功的,后续的写入应该抛出异常或者空操作,或者执行了写入但是未对数据造成变化。对于读取类操作,需要保证其实现上是真正的读取,不能在读操作中夹带写操作。

场景

需要实现幂等性的典型场景有以下两种:

客户端发起的请求可能需要重试,请求的后端处理需要保证幂等

后端系统使用同步RPC调用或异步消息实现分布式事务,消息的消费者需要保证幂等

必要性

重试是降低系统失败率的重要手段。

广义上的RPC,包括客户端对服务端的api调用、后端系统的内网调用、跨机房调用等。一次RPC大体上包括三个步骤:发送请求、执行过程、接收响应。由于网络传输存在不确定性,导致RPC调用存在一个陷阱,即有可能出现第一、第二步都成功、第三步失败的情况,此时RPC的调用方由于接收不到结果,无法判断被调用方是否已经完成过程调用,只能按失败处理。

通常RPC调用方会针对网络失败进行重试。在上述情况下,如果远端代码不具备幂等性,却进行了重试,将导致系统的数据一致性遭到破坏,本该只执行一次的事务被执行了两次。

对于异步消息的消费者来讲,也有同样的问题。在手动ACK的情况下,消息的处理需要接收消息、处理消息、ACK三步,ACK的失败也会导致相同的问题。

在交易类的系统(比如电商、证券等)中,对非幂等的远程过程进行重试,可能会导致超买超卖,对客户造成经济损失。

互联网应用一般都是提供7*24服务的,而互联网应用本身又是快速迭代,后端系统是随时有可能需要进行发布的。发布等同于一次宕机(进程被kill),这意味着对于互联网应用的后端系统,宕机是常态而非特例。这也是幂等性和重试的必要性来源之一。

可重入性

幂等性在技术上同时要求可重入性。在分布式系统中,重试和并发都是常态,允许多次调用代码也应该支持并发调用。分布式锁(包括数据库锁)可以解决这一问题。

技术实现

本地事务的幂等性

考虑简单的增删改查四类操作:

select,天生幂等

insert,数据库自增主键时不具备幂等

基于主键update,具备幂等,但是带查询的更新除外(形如update t set x = x + 1 where ...)

基于主建delete,具备幂等

非基于主键的udpate/delete操作,需要具体问题具体分析

在分布式系统中,带条件的或带子查询的增删改操作应当慎用,除了非幂等性问题以外,还有可能带来死锁问题。

很显然,如果一个事务中所有数据库操作都是幂等操作,且不存在外部调用,那么该事务一定也是幂等的。

如果事务中存在非幂等的数据库操作,唯一键为本地事务的幂等性提供了实现基础。使用带有唯一键的去重表,在事务中先执行insert去重表,再执行其他业务操作,然后提交事务,事务过程中出现异常回滚事务,可以保证事务的幂等性。

考虑两种失败的情况。

Insert去重表失败,事务回滚,无任何影响,调用方应停止重试

Insert去重表成功,业务操作失败,事务回滚,之前插入的记录也将消失,无任何影响,调用方可以选择重试

以上两种失败的情况下,事务的幂等性是可以保证的。

补充说明,在使用JDBC连接MySQL的情况下,如果程序需要捕获唯一键冲突异常,可以catch com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException。

本地事务并发情况

在并发的情况下,如果两个(数据库的)客户端同时执行该事务且唯一键相同,此时唯一键能直到分布式锁的作用。

这里以示例来说明。打开两个命令行终端,连接同一个MySQL数据库,称之为A和B。

先在任意一端创建测试表

1create table tt (id int primary key);

在两端依次执行

1set autocommit = false;

在A端执行

1insert into tt (id) values (1);

返回

1Query OK, 1 row affected (0.00 sec)

在B端执行同样的insert语句

1insert into tt (id) values (1);

此时B端会挂起。

如果在A端执行

1commit;

A端会提交成功,而B端会立即结束挂起,报错,等于获取锁失败。

1ERROR 1062 (23000): Duplicate entry '1' for key 'PRIMARY'

如果A端执行

1rollback;

或直接关闭终端,B端则会立即结束挂起且insert成功,等于获取锁成功。

通过这个实验,同时也可以得出,数据库的唯一键可以用于实现通用的分布式锁。

分布式事务的幂等性

要保证分布式事务的幂等性,需要各个子事务都保证幂等性,否则整体幂等性的很难实现。

在基于关系型数据库的系统中,分布式事务最终还是要依靠数据库的本地事务来实现事务的ACID。

考虑存在A、B两个子系统分别实现各自的事务,需要整合为一个分布式事务,其中A系统的本地事务基于MySQL实现,保证幂等;B系统的本地事务也保证幂等,对外提供RPC服务接口,其具体实现这里不关心。

在这种情况下,有一个简单的不需要事务仲裁者的分布式事务方案,就是在A事务中嵌套对B的调用。具体流程是A事务先执行本地数据库操作,再调用B接口,然后提交事务。

同样,考虑三种失败的情况。

A本地操作失败,事务回滚,无任何影响

A本地操作成功,调用B失败,如果是唯一性冲突导致的失败,A正常提交;如果是其他失败,事务回滚,此时外部调用方可以重试

很极端的情况,A本地操作成功,调用B成功,事务提交失败,此时外部调用方可以重试

这个方案并不是一个高可靠的解决方案,但是实现上非常简单。

其缺陷在于如果外部调用方没有进行重试,那么可能会产生对B的多余调用。当然,如果在业务上对B的少量多余调用是可接受的,比如B是次要业务,那这个方案也是可以用的。

另外由于在DB事务中嵌套了耗时操作(RPC调用),事务的耗时也因此延长,数据库连接被事务占用不能复用,系统的吞吐量会受到影响。

分布式事务不可能实现绝对的一致性。我们应该从概率的角度思考问题,如果能将不一致的概率降到最低,比如保证幂等性加重试,再辅以业务监控和人工干预,就可以实现系统整体上较高的一致性。

幂等性设计

幂等性设计不能脱离业务来讨论。一般情况下,去重表同时也是业务数据表。对于唯一键,这里提供两种设计思路:

在请求参数中附带唯一标识作为唯一键,唯一标识可以由业务字段加时间戳低位拼接而成,或者使用snowflake、UUID等ID生成算法

找出业务本身的唯一约束。比如一个客户对同一只新股只能申购一次,那么客户号加申购代码可以组成唯一键

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/501000.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python re模块compile_Python re模块的match方法

pattern re.compile("\d") 将正则表达式编译成一个Pattern规则对象 pattern.match() 从开始位置开始往后查找,返回第一个符合规则的对象 pattern.search() 从任何位置开始往后查找,返回第一个符合规则的对象 pattern.findall() 所有的全部匹配…

考研数学(180°为什么等于π)

之所以要定义弧度制,是因为它的单位相比角度制有很大的优越性. 弧度的大小是两个长度之比,长度的单位是统一的,所以相比以后,可以认为弧度的单位为1,即以实数单位为单位. 弧度可以看做导出单位. 而角度制则不然,角度制单位是1/360周角,然而,1/360是怎么来的?为什么是周角除360…

c++ h cpp文件如何关联_C++核心准则SF.5: .cpp文件必须包含定义它接口的.h文件

SF.5: A .cpp file must include the .h file(s) that defines its interfaceSF.5: .cpp文件必须包含定义它接口的.h文件Reason(原因)This enables the compiler to do an early consistency check.这样可以让编译器尽早进行一致性检查。Example, bad(反面示例)// foo.h:void f…

常用的python脚本_五个python常用运维脚本面试题实例

一、用Python写一个列举当前目录以及所有子目录下的文件,并打印出绝对路径 #!/usr/bin/env python import os for root,dirs,files in os.walk(/tmp): for name in files: print (os.path.join(root,name)) os.walk() 原型为:os.walk(top, topdownTrue, …

JAVA进阶教学之(IO流)

目录 1、什么是IO流 2、流的分类 3、流的四大家族首领 4、java.io.*包下需要掌握的16个流 5、FileInputStream的实用方法 6、FileOutputStream的方法 7、文件复制/拷贝 8、FileReader的使用 9、FileWriter的使用 10、复制普通文本文件 11、BufferedReader带有缓冲区…

sonar 代理_Sonar

关于Sonar费用:免费;更新频率:持续更新;搜索来源:亚马逊;关键词总数:美国站约1亿,全球约1.8亿;关键词反查:支持;PPC关键词查询:支持;其他功能:关键词翻译。功能1、亚马逊PPC管理&…

devtools安装_R语言如何批量安装软件包

1. 为什么要批量安装R语言包当你在新的环境下, 安装R语言时,你需要安装很多包,比如tidyverse,比如data.table,这里你可以写一个函数,将所有需要的包写进去,然后进行批量安装2. 程序如下&#xf…

JAVA进阶教学之(序列化和反序列化)

目录 1、序列化Serialize和反序列化的概念 2、序列化和反序列化的代码演示: 3、序列化多个对象(序列化集合) 4、transient关键字将部分属性不参与序列化 1、序列化Serialize和反序列化的概念 在内存和硬盘的数据交互过程中,将…

java如何实现e的次方_Java开发如何更改MySQL数据库datadir目录之MySQL数据库索引实现...

引言MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,目前属于 Oracle 旗下产品。MySQL 是最流行的关系型数据库管理系统之一,在 WEB 应用方面,MySQL是最好的 RDBMS (Relational Database Management System&#xff0c…

pythonjieba分词_$好玩的分词——python jieba分词模块的基本用法

jieba(结巴)是一个强大的分词库,完美支持中文分词,本文对其基本用法做一个简要总结。 安装jieba pip install jieba 简单用法 结巴分词分为三种模式:精确模式(默认)、全模式和搜索引擎模式&…

局部变量和成员变量的区别

1.定义的位置不一样【重点】 局部变量:在方法的内部成员变量:在方法的外部,直接写在类当中 2.作用范围不一样【重点】 局部变量:只有方法当中才可以使用,出了方法就不能再用了成员变量:整个类都可以通用 …

pytorch 训练过程acc_Pytorch之Softmax多分类任务

在上一篇文章中,笔者介绍了什么是Softmax回归及其原理。因此在接下来的这篇文章中,我们就来开始动手实现一下Softmax回归,并且最后要完成利用Softmax模型对Fashion MINIST进行分类的任务。在开始实现Softmax之前,我们先来了解一下…

进程调度实验_Linux应用编程之进程的PID与PPID

关注、星标公众号,直达精彩内容ID:嵌入式情报局作者:情报小哥1进程PID首先介绍PID的相关知识,为后面介绍fork函数进行铺垫。01PID与PPID PID不是控制理论的PID算法,而是Prcess ID的简写。进程PID是当操作系统运行进程时…

操作Windows文件夹时,弹出文件夹正在使用,操作无法完成【解决】

在windows系统上,有时候在删除系统文件或文件夹时出现弹框,提示操作无法完成。这种情况的出现是因为你要删除的文件或文件夹被打开,或者被系统占用。遇到这种情况要怎么处理呢,本文介绍下具体的操作方法来帮助你解决这个问题。 方…

邀请合作如何表达_适时表达想法 才有利于彼此的合作

丹尼跟珍妮合作主持一个podcast节目,两人对这个节目兴致勃勃,并花很多时间投入,珍妮想邀请自己身边朋友一起参加,认为特别来宾可以增加节目的丰富度;丹尼却觉得现在节目才刚开始起步,要建立好两人的节目定位…

python泰坦尼克号数据预测_使用python预测泰坦尼克号生还

简介Titanic是Kaggle竞赛的一道入门题,参赛者需要根据旅客的阶级、性别、年龄、船舱种类等信息预测其是否能在海难中生还,详细信息可以参看https://www.kaggle.com/,本文的分析代码也取自 kaggle 中该竞赛的 kernal。数据介绍给出的数据格式如…

idea代码可以编译但是爆红_推荐一款 IDEA 生成代码神器,写代码再也不用加班了...

作者:HeloWxl链接:https://www.jianshu.com/p/e4192d7c6844Easycode是idea的一个插件,可以直接对数据的表生成entity,controller,service,dao,mapper,无需任何编码,简单而强大。1、安装(EasyCode)我这里的话是已经那装好了。建议大…

html跑马灯_用Excel居然能做“跑马灯”,而且还这么简单!

我的目标:让中国的大学生走出校门的那一刻就已经具备这些office技能,让职场人士能高效使用office为其服务。支持我,也为自己加油!你没看错,上面这个就是用Excel做出来的,不过要用到窗体和控件。步骤如下&am…

c语言双链表排序交换节点_图解:单链表翻转的三种方式!

当我们在聊到链表反转的时候,一定说的都是单链表,双链表本身就具有前驱指针 Prev 和后续指针 next,无需进行翻转。单链表反转,反转后的效果如下:看起来很简单,只需要将单链表所有结点的 next 指向&#xff…

wsdl文档中的soap:address的生成规则_BAT大牛都在使用的数据库文档生成插件,不来看一下?...

一、概述在企业级开发中、我们经常会有编写数据库表结构文档的时间付出,从业以来,待过几家企业,关于数据库表结构文档状态:要么没有、要么有、但都是手写、后期运维开发,需要手动进行维护到文档中,很是繁琐…