如何解决重复提交造成的数据重复

理解HTTP幂等性
基于HTTP协议的Web API是时下最为流行的一种分布式服务提供方式。无论是在大型互联网应用还是企业级架构中,我们都见到了越来越多的SOA或RESTful的Web API。为什么Web API如此流行呢?我认为很大程度上应归功于简单有效的HTTP协议。HTTP协议是一种分布式的面向资源的网络应用层协议,无论是服务器端提供Web服务,还是客户端消费Web服务都非常简单。再加上浏览器、Javascript、AJAX、JSON以及HTML5等技术和工具的发展,互联网应用架构设计表现出了从传统的PHP、JSP、ASP.NET等服务器端动态网页向Web API + RIA(富互联网应用)过渡的趋势。Web API专注于提供业务服务,RIA专注于用户界面和交互设计,从此两个领域的分工更加明晰。在这种趋势下,Web API设计将成为服务器端程序员的必修课。然而,正如简单的Java语言并不意味着高质量的Java程序,简单的HTTP协议也不意味着高质量的Web API。要想设计出高质量的Web API,还需要深入理解分布式系统及HTTP协议的特性。

幂等性定义
本文所要探讨的正是HTTP协议涉及到的一种重要性质:幂等性(Idempotence)。在HTTP/1.1规范中幂等性的定义是:

Methods can also have the property of “idempotence” in that (aside from error or expiration issues) the side-effects of N > 0 identical requests is the same as for a single request.
从定义上看,HTTP方法的幂等性是指一次和多次请求某一个资源应该具有同样的副作用。幂等性属于语义范畴,正如编译器只能帮助检查语法错误一样,HTTP规范也没有办法通过消息格式等语法手段来定义它,这可能是它不太受到重视的原因之一。但实际上,幂等性是分布式系统设计中十分重要的概念,而HTTP的分布式本质也决定了它在HTTP中具有重要地位。

分布式事务 vs 幂等设计
为什么需要幂等性呢?我们先从一个例子说起,假设有一个从账户取钱的远程API(可以是HTTP的,也可以不是),我们暂时用类函数的方式记为:

bool withdraw(account_id, amount)
withdraw的语义是从account_id对应的账户中扣除amount数额的钱;如果扣除成功则返回true,账户余额减少amount;如果扣除失败则返回false,账户余额不变。值得注意的是:和本地环境相比,我们不能轻易假设分布式环境的可靠性。一种典型的情况是withdraw请求已经被服务器端正确处理,但服务器端的返回结果由于网络等原因被掉丢了,导致客户端无法得知处理结果。如果是在网页上,一些不恰当的设计可能会使用户认为上一次操作失败了,然后刷新页面,这就导致了withdraw被调用两次,账户也被多扣了一次钱。如图1所示:

non-idempotent

图1这里写图片描述

这个问题的解决方案一是采用分布式事务,通过引入支持分布式事务的中间件来保证withdraw功能的事务性。分布式事务的优点是对于调用者很简单,复杂性都交给了中间件来管理。缺点则是一方面架构太重量级,容易被绑在特定的中间件上,不利于异构系统的集成;另一方面分布式事务虽然能保证事务的ACID性质,而但却无法提供性能和可用性的保证。

另一种更轻量级的解决方案是幂等设计。我们可以通过一些技巧把withdraw变成幂等的,比如:

int create_ticket()
bool idempotent_withdraw(ticket_id, account_id, amount)
create_ticket的语义是获取一个服务器端生成的唯一的处理号ticket_id,它将用于标识后续的操作。idempotent_withdraw和withdraw的区别在于关联了一个ticket_id,一个ticket_id表示的操作至多只会被处理一次,每次调用都将返回第一次调用时的处理结果。这样,idempotent_withdraw就符合幂等性了,客户端就可以放心地多次调用。

基于幂等性的解决方案中一个完整的取钱流程被分解成了两个步骤:1.调用create_ticket()获取ticket_id;2.调用idempotent_withdraw(ticket_id, account_id, amount)。虽然create_ticket不是幂等的,但在这种设计下,它对系统状态的影响可以忽略,加上idempotent_withdraw是幂等的,所以任何一步由于网络等原因失败或超时,客户端都可以重试,直到获得结果。如图2所示:

idempotent

图2
这里写图片描述
和分布式事务相比,幂等设计的优势在于它的轻量级,容易适应异构环境,以及性能和可用性方面。在某些性能要求比较高的应用,幂等设计往往是唯一的选择。

HTTP的幂等性
HTTP协议本身是一种面向资源的应用层协议,但对HTTP协议的使用实际上存在着两种不同的方式:一种是RESTful的,它把HTTP当成应用层协议,比较忠实地遵守了HTTP协议的各种规定;另一种是SOA的,它并没有完全把HTTP当成应用层协议,而是把HTTP协议作为了传输层协议,然后在HTTP之上建立了自己的应用层协议。本文所讨论的HTTP幂等性主要针对RESTful风格的,不过正如上一节所看到的那样,幂等性并不属于特定的协议,它是分布式系统的一种特性;所以,不论是SOA还是RESTful的Web API设计都应该考虑幂等性。下面将介绍HTTP GET、DELETE、PUT、POST四种主要方法的语义和幂等性。

HTTP GET方法用于获取资源,不应有副作用,所以是幂等的。比如:GET http://www.bank.com/account/123456,不会改变资源的状态,不论调用一次还是N次都没有副作用。请注意,这里强调的是一次和N次具有相同的副作用,而不是每次GET的结果相同。GET http://www.news.com/latest-news这个HTTP请求可能会每次得到不同的结果,但它本身并没有产生任何副作用,因而是满足幂等性的。

HTTP DELETE方法用于删除资源,有副作用,但它应该满足幂等性。比如:DELETE http://www.forum.com/article/4231,调用一次和N次对系统产生的副作用是相同的,即删掉id为4231的帖子;因此,调用者可以多次调用或刷新页面而不必担心引起错误。

比较容易混淆的是HTTP POST和PUT。POST和PUT的区别容易被简单地误认为“POST表示创建资源,PUT表示更新资源”;而实际上,二者均可用于创建资源,更为本质的差别是在幂等性方面。在HTTP规范中对POST和PUT是这样定义的:

The POST method is used to request that the origin server accept the entity enclosed in the request as a new subordinate of the resource identified by the Request-URI in the Request-Line …… If a resource has been created on the origin server, the response SHOULD be 201 (Created) and contain an entity which describes the status of the request and refers to the new resource, and a Location header.

The PUT method requests that the enclosed entity be stored under the supplied Request-URI. If the Request-URI refers to an already existing resource, the enclosed entity SHOULD be considered as a modified version of the one residing on the origin server. If the Request-URI does not point to an existing resource, and that URI is capable of being defined as a new resource by the requesting user agent, the origin server can create the resource with that URI.
POST所对应的URI并非创建的资源本身,而是资源的接收者。比如:POST http://www.forum.com/articles的语义是在http://www.forum.com/articles下创建一篇帖子,HTTP响应中应包含帖子的创建状态以及帖子的URI。两次相同的POST请求会在服务器端创建两份资源,它们具有不同的URI;所以,POST方法不具备幂等性。而PUT所对应的URI是要创建或更新的资源本身。比如:PUT http://www.forum/articles/4231的语义是创建或更新ID为4231的帖子。对同一URI进行多次PUT的副作用和一次PUT是相同的;因此,PUT方法具有幂等性。

在介绍了几种操作的语义和幂等性之后,我们来看看如何通过Web API的形式实现前面所提到的取款功能。很简单,用POST /tickets来实现create_ticket;用PUT /accounts/account_id/ticket_id&amount=xxx来实现idempotent_withdraw。值得注意的是严格来讲amount参数不应该作为URI的一部分,真正的URI应该是/accounts/account_id/ticket_id,而amount应该放在请求的body中。这种模式可以应用于很多场合,比如:论坛网站中防止意外的重复发帖。

总结
上面简单介绍了幂等性的概念,用幂等设计取代分布式事务的方法,以及HTTP主要方法的语义和幂等性特征。其实,如果要追根溯源,幂等性是数学中的一个概念,表达的是N次变换与1次变换的结果相同,有兴趣的读者可以从Wikipedia上进一步了解。

参考
RFC 2616, Hypertext Transfer Protocol – HTTP/1.1, Method Definitions
The Importance of Idempotence
Stackoverflow - PUT vs POST in REST

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

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

相关文章

中大计算机研究生华为,考上中山大学很厉害吗?毕业后有机会去华为吗?本文有答案...

原标题:考上中山大学很厉害吗?毕业后有机会去华为吗?本文有答案 声明:本文转载自网络,如有侵权,请在后台留言联系我们进行删除,谢谢! 中山大学是全国知名985高校,也是广东…

到底要不要报考“通信工程”?

作者 | 小枣君 来源 | 鲜枣课堂 “通信工程”是干嘛的 通信工程,英文全称叫做Communication Engineering,是一门重要的工学基础学科。 根据教育部《学位授予和人才培养学科目录设置与管理办法》,“通信工程”属于二级学科,归属于“…

我通过了软考高项,有些话想说

文章目录 1. 软考成绩2. 备考过程与经验3. 遇到的坑4. 论文准备5. 资料及寄语 1. 软考成绩 昨天下午得到了一个振奋人心的消息,我的软考通过了,感觉努力没有白费很欣慰,也感觉有很多话要说(真不是得瑟)。可能很多人不…

大学报考计算机相关专业,这份指南收好,最新数据

2022年的高考已经结束了,但却并不代表高考落幕了,因为后面的报考学校和专业更是一轮重头戏,几年的寒窗苦读自然是要考上一个好学校好专业,才算真正给自己生涯划上句号。 今天给大家分享的计算机相关专业的实际情况,包…

测试高考分数能上什么大学的软件,测你能考上哪所大学软件是什么

测你能考上哪所大学软件是什么,小编整理了相关信息,来看一下! 测你能考上哪所大学软件 蝶变志愿 蝶变志愿是是为帮助高三考生和家长学习高考志愿填报知识,查询院校和专业信息的软件。软件包含教育部公布的所有大学的信息和1800多种…

某程序员自述:我,三十多岁,逃离北上广,通过技术移民到加拿大!

本文转载自 程序员八卦 在北上广的巨大压力下,许多人选择逃离,有人“逃”回了老家,有人则“逃”到了国外,之前我们分享过一个“逃”到新加坡的程序员故事,今天再来分享一个“逃”到加拿大的程序员故事。 这是一位已经…

2019全球数据新闻奖揭晓

大数据文摘授权转载自RUC新闻坊 编辑:刘长宇、刘畅、段钇男、葛书润、肖鳕桐、姚思妤、欧阳婕、马冰莹 2019年全球数据新闻奖于当地时间6月14日(北京时间6月15日)在希腊揭晓,本次评选共收到参赛作品607件,经过初选&…

全球最大NFT交易平台OpenSea

文章目录 全球最大NFT交易平台OpenSea背景什么是OpenSea发展历史OpenSea都支持哪些公链 参考 全球最大NFT交易平台OpenSea 背景 Ethereum上NFT销售额在2021年已超过90亿美元,比2020年的总销售额增长了2500%。2021年作为NFT元年,同时出现在牛市周期的背…

加拿大java技术移民_加拿大技术移民分析贴之新手入门级!

释放双眼,带上耳机,听听看~! 加拿大技术移民分析贴之新手入门级! 能力 学历 申请能力 学历 申请能力 学历 申请 移民加拿大有很多种方式,加拿大技术移民是最主要的方式之一,也是加拿大移民重要组成部分&…

科技巨头打响第一枪!“我们将要被AI取代”?

来源:量子位 “这不是演习,AI让人失业来真的了!” 就在这个劳动节假期,科技巨头IBM宣布: 暂缓可以被AI取代的岗位的招聘,约7800人将被永久淘汰。 尽管“我们要被AI取代”的唬人消息不是第一次出现了&#x…

如何用AI技术实现和马斯克实时视频聊天

前言 在直播盛行、短视频横飞、主播满地的今天,个人上传自己的生活视频来记录日常已经屡见不鲜了。拿起手机拍个视频,并且在上传前顺便美颜一下,乐此不疲。 但是最近看到的一些AI诈骗新闻却不得不令人担忧,网上你以为的帅哥美女、…

这段视频火爆外网,谷歌把AI视频造假搞得太真太简单了

来源:量子位 家人们,AI做视频这事今天又被推向了舆论的风口浪尖。 起因是有人在网上发布了这么一只小企鹅的视频: 而这个近50秒视频的诞生,靠的仅仅是6句话! 陆陆续续的,网友们还在发布着这个AI的其它杰作&…

2020AI顶会的腾讯论文解读 | 多模态学习、视频内容理解、对抗攻击与对抗防御等「AI核心算法」

关注:决策智能与机器学习,深耕AI脱水干货 报道 | 腾讯AI实验室 计算机视觉领域三大顶会之一的 ECCV(欧洲计算机视觉会议)今年于 8 月 23-28 日举办。受新冠肺炎疫情影响,今年的 ECCV 与 CVPR 一样是完全的线上会议。近…

豪气!华为放话:3年培养100万AI人才!网友神回应了

大家经常把BAT挂在嘴边,但是可能有些人还不知道,华为的体量早已超越了这三巨头,只是迟迟不肯上市。华为的创始人任正非曾说表:上不上市不重要,最重要的是要让中国华为的技术能够称霸全球! 华为对技术的重视…

豪投10亿!华为放话:3年培养100万AI人才!网友神回应了

近期,AI测试权威软件AI Benchmark的测试数据显示,中国华为研发的7nm旗舰手机芯片麒麟810的AI分数,远远超过美国高通骁龙855了! 麒麟810芯片AI分数是3300多,名列第一。而骁龙855手机则是2700多。 大家振奋的同时&#…

ETH今日全网算力上涨3.14%

消息面:BTC全网算力123.098EH/s,挖矿难度16.85T,目前区块高度642856,理论收益0.00000809/T/天。 ETH全网算力201.064TH/s,挖矿难度2535.06T,目前区块高度10622682,理论收益0.00911583/100MH/天。 BSV全网算力2.305EH/s,挖矿难度0.32T,目前区块高度647319,理论收益0.0…

一分钟配置Openai api接口代理

目录 目录 目录一、首先需要一个国外的云服务器二、搭建步骤1.连接服务器2.安装宝塔2.服务器安装以及配置 答疑合作 一、首先需要一个国外的云服务器 这里推荐这个。链接:衡天云 二、搭建步骤 1.连接服务器 可使用xshell或者自带的vnc直接连接,账号密…

ChatGPT预示着人类文明的终结?丨小智ai

ChatGPT丨小智ai丨chatgpt丨人工智能丨OpenAI丨聊天机器人丨AI语音助手丨GPT-3.5丨OpenAI ChatGPT|GPT-4|GPT-3|人机对话|ChatGPT应用|小智ai|小智ai|小智ai|小智ai|小智AI|chatgpt小智AI 人工智能(AI)的快速发展和广泛应用给我们的社会带来了前所未有的…

跟ChatGPT聊天、需求润色优化,禅道OpenAI 插件发布

禅道插件上新了,OpenAI 禅道集成,可提供神奇海螺聊天、需求润色功能。 神奇海螺 “章鱼哥,你为什么不问问神奇海螺呢?”——海绵宝宝 那么,就让我们问一问神奇 海螺吧!禅道上线神奇海螺功能,…