幂等和高并发在电商系统中的使用

在Java web项目开发中,经常会听到在做订单系统中生成订单的时候,要做幂等性控制和并发控制,特对此部分内容作出总结,在高并发场景下,代码层面需要实现并发控制;但是幂等性,其实更多的是系统的接口对外的一种承诺,承诺一次请求和多次请求会返回同样的数据。关于幂等性将分别从高等代数中的幂等性、HTTP中的幂等性和订单生成系统中的幂等性阐述;并发性控制则提供了分布式锁等方式来对并发场景进行代码实现。

一、幂等性 idempotence  ['aɪdəmpoʊtəns]

1.高等代数中关于幂等idempotence概念解释:

  单目运算, x为某集合内的任意数, 如果满足f(x)=f(f(x)), 那么我们称f运算为具有幂等性(idempotent)。比如在实数集中,绝对值运算就是一个例子: abs(a)=abs(abs(a))。

  双目运算,x为某集合内的任意数, f为运算子如果满足f(x,x)=x, f运算的前提是两个参数都同为x, 那么我们也称f运算为具有幂等性。比如在实数集中,求两个数的最大值的函数: max(x,x) = x, 还有布尔代数中,逻辑运算 "与", "或" 也都是幂等运算, 因为他们符合AND(0,0) = 0, AND(1,1) = 1, OR(0,0) = 0, OR(1,1) = 1。

在将幂等性应用到软件开发中,需要一些更深的理解,我的理解如下:数学处理的是运算和数值, 程序开发中往往处理的是对象和函数. 但是我们不能简单地理解为数学幂等中的运算就是函数,而数值就是对象。如Person对象有两个属性weight和age,但是所有的function只能对其中一个属性操作。所以从这个层面我们可以理解为: 函数只对该函数所操作的对象某个属性具有幂等性, 而不是说对整个对象有运算幂等性。 

Person { private int weight; private int age; //是幂等函数public void setAge(int v){ this.age = v; }//不是幂等函数public void increaseAge(){ this.age++;} //是幂等函数public void setWeight(int v){ this.weight=v+10;//故意加10斤!!
    }
}

还有一点必须要澄清的是: 幂等性所表达的概念关注的是数学层面的运算和数值, 并没有提及到数值的安全性问题.如上面的Person的setAge函数, 有两种case不是幂等性所关心的, 但程序开发却又必须要关心的:

  • 两个线程同时调用
  • 因为age从业务上讲不可能递减, 如果前一次调用设置是30岁, 后一次调用变成了10岁或是更离谱的 -1 岁

幂等性是系统的接口对外一种承诺(而不是实现), 承诺只要调用接口成功, 外部多次调用对系统的影响是一致的。声明为幂等的接口会认为外部调用失败是常态, 并且失败之后必然会有重试。所以RESTful设计中将幂等性和安全性作为两个不同的指标来衡量POST,PUT,GET,DELETE操作的。因此,post不是幂等性的,put get delete都是幂等性的,也即在生成订单的post请求中,我们要做幂等性的控制。如下图,一个ajax请求是一次post请求的示例,如果这个post请求被调用多次,它会向表插入多条记录,很显然post请求并不是幂等性的,所以幂等性的控制交由我们程序中来控制。

2.HTTP协议中的幂等性

  项目中中的SOA和restful API接口的流行,都需要应用层HTTP协议的支持,目前的项目结构:Web API + RIA(Rich Internet Applications富互联网应用),Web API专注于提供业务服务,RIA专注于用户界面和交互设计,从此两个领域的分工更加明晰。正如简单的Java语言并不意味着高质量的Java程序,简单的HTTP协议也不意味着高质量的Web API。要想设计出高质量的Web API,还需要深入理解分布式系统及HTTP协议的特性。在HTTP1.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中具有重要地位。比如有这样一个业务逻辑,假设有一个从账户取钱的远程API(可以是HTTP的,也可以不是),我们暂时定义接口:

bool withdraw(account_id, amount)

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

 

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

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

int create_ticket() 
bool idempotent_withdraw(ticket_id, account_id, amount)

create_ticket的语义是获取一个服务器端生成的唯一的处理号token,它将用于标识后续的操作。idempotent_withdraw和withdraw的区别在于关联了一个token,一个token表示的操作至多只会被处理一次,每次调用都将返回第一次调用时的处理结果。这样,idempotent_withdraw就符合幂等性了,客户端就可以放心地多次调用。也就是说,多次点击提交的时候,附带提交的还有服务端生成的token,由于多次提交带的是同一个token,所以服务端对于同一个token的post订单,至多只会处理一次,所以间接的实现了幂等性的控制

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

 

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

  1. HTTP GET方法用于获取资源,不应有副作用,所以是幂等的。比如:GET http://www.bank.com/account/123456,不会改变资源的状态,不论调用一次还是N次都没有副作用。请注意,这里强调的是一次和N次具有相同的作用,而不是每次GET的结果相同。GET http://www.news.com/latest-news这个HTTP请求可能会每次得到不同的结果,但它本身并没有产生任何副作用,因而是满足幂等性的。
  2. HTTP DELETE方法用于删除资源,有副作用,但它应该满足幂等性。比如:DELETE http://www.forum.com/article/4231,调用一次和N次对系统产生的副作用是相同的,即删掉id为4231的帖子;因此,调用者可以多次调用或刷新页面而不必担心引起错误。
  3. 比较容易混淆的是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方法具有幂等性。论坛网站防止重复发帖和订单生成都用到token方式的幂等性控制。

3.总结

  在电商系统中,常见问题:如何防范post请求的重复提交?HTTP POST 操作既不是安全的,也不是幂等的。当我们因为反复刷新浏览器导致多次提交表单,多次发出同样的POST请求,导致远端服务器重复创建出了资源。所以,对于电商应用来说,第一对应的后端 WebService 一定要做到幂等性,第二服务器端收到 POST 请求,在操作成功后必须跳转到另外一个页面,这样即使用户刷新页面,也不会重复提交表单

二、高并发

1.分布式锁的定义

  分布式锁是控制分布式系统之间同步访问共享资源的一种方式。在分布式系统中,常常需要协调他们的动作。如果不同的系统或是同一个系统的不同主机之间共享了一个或一组资源,那么访问这些资源的时候,往往需要互斥来防止彼此干扰来保证一致性,在这种情况下,便需要使用到分布式锁。分布式锁是一个在很多环境中非常有用的原语,它是不同的系统或是同一个系统的不同主机之间互斥操作共享资源的有效方法。如在电商系统中,需要保证整个分布式系统内,对一个重要事物(订单,账户等)的有效操作线程 ,同一时间内有且只有一个。比如交易中心有N台服务器,订单中心有M台服务器,如何保证一个订单的同一笔支付处理,一个账户的同一笔充值操作是原子性的。

  常见的实现分布式锁的服务有:memcache zookeeper redis chubby hazelcast。

2.分布式锁实现

  分布式锁在分布式应用当中是要经常用到的,主要是解决分布式资源访问冲突的问题。传统的锁ReentrantLock在去实现的时候是有问题的,ReentrantLock的lock和unlock要求必须是在同一线程进行,而分布式应用中,lock和unlock是两次不相关的请求,因此肯定不是同一线程,因此导致无法使用ReentrantLock。

附:

1、什么是restful风格的API接口?

http://www.ruanyifeng.com/blog/2014/05/restful_api.html

http://www.cnblogs.com/zhengyun_ustc/archive/2012/11/17/topic2.html

http://www.cnblogs.com/j2eetop/p/4612437.html

http://www.cnblogs.com/weidagang2046/p/exception-handling-principles.html

http://www.cnblogs.com/orange1438/p/4637776.html

 

转载于:https://www.cnblogs.com/RunForLove/p/5640949.html

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

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

相关文章

@transactional注解失效情况

先来了解一下Transactional注解事务的特性吧,可以更好排查问题 1、service类标签(一般不建议在接口上)上添加Transactional,可以将整个类纳入spring事务管理,在每个业务方法执行时都会开启一个事务,不过这些事务采用相同的管理方…

计算机c盘隐藏了怎么办,win7怎么隐藏c盘 win7c盘被隐藏了怎么解除

很多的电脑用户担心其他用户在使用电脑时修改c盘中的重要文件,所以会将c盘设置为隐藏,那么大家知道在win7系统中怎么隐藏c盘吗?方法很简单,下面小编为大家带来win7隐藏c盘的详细教程,不知道怎么隐藏的朋友可以查看下面的教程学习…

操作系统基础:存储管理知识笔记(二)

一、分页存储管理 1、分页存储管理介绍 1.1 分页原理 页:将一个进程的地址空间划分为若干个大小相等的区域称为页。 块、页框:主存空间划分成与页相同的若干个物理块。 1.2 地址结构 分页系统地址结构:前一部分为页号;后一部分为页…

人工智能 信道估计 深度学习_DEMO演示|基于IVP02D 人工智能工作站的深度学习引擎,实现人群热力估计...

近年来,随着深度学习在计算机视觉领域获得广泛应用,算法框架也日渐成熟,例如基于深度神经网络的人群密度分析,通过自动学习能获得更有效的人群特征,相较于传统方法取得了一定的提高。AI小知识人群密度分析(…

vscode kite插件_微软发布 VS Code Python 插件 7 月更新

微软发布了 7 月的 Visual Studio Code Python 扩展更新,此版本总共修复了 51 个问题,其中包括:支持新的语言服务器:PylanceGather 扩展将 Notebook 导出为 HTML 和 PDF调试器的反向连接支持新的语言服务器:PylancePyl…

360浏览器打不开微信的连接服务器,上午还能打开,下午360浏览器打不开微信公 – 手机爱问...

2011-08-27ie,搜狗,谷歌浏览器都打不开,说打不开ipad说服务器超时是新浪在更新设备吗?一般你能进入爱问就可以进入邮箱,下面的方法看看(如果你是铁通的可能是铁通的问题)。可能是服务器故障引起的,请不要着…

域名还能绑定动态IP?看完又涨知识了!!

点击上方蓝色“冰河技术”,关注并选择“设为星标”持之以恒,贵在坚持,每天进步一点点!作者个人研发的在高并发场景下,提供的简单、稳定、可扩展的延迟消息队列框架,具有精准的定时任务和延迟队列处理功能。…

java 及时释放内存_JMM(一):初识Java内存模型

在并发编程中,线程之间的通信是一个很关键的问题,而该问题解决方案主要可分为两大类:消息传递、共享内存。前者有以Erlang语言为代表的Actor模型,而后者中典型的则是Java语言。对于消息传递机制而言,线程之间必须通过发…

电脑维修知识:电脑常见故障维修大全及解决方法

电脑已经成为我们学习生活娱乐必不可少的设备了,用得时间久了难免会遇到小故障,今天我们一起来看下遇到常见的电脑方面的小故障,我们应该如何去自己检测和维修吧。电脑检测故障我们还是要从电脑的几大硬件开始检查起。1、CPU打开机箱查看CPU风…

工程图样中粗实线的用途_图纸天天画,粗实线和细实线的线宽比例是多少?2:1还是3:1?...

点击上方头条号“机械设计一点通”关注我们,每天学习一个机械设计相关知识点我们知道:机械制图中为了表示不同内容,并能分清主次,必须使用不同线型。图线的线型由线宽和线素长度等构成,机械制图中各种线型都有相应宽度…

STM32F4_USART配置及细节描述

Ⅰ、概述 关于USART串口通信,可以说是MCU的标配。不管是在实际项目应用中,还是在开发过程中,它都起着很重要的作用。 在项目应用中我们常常使用UART串口进行通信,根据通信的距离及稳定性,还选择添加RS232、RS485等对UA…

腾讯面试:SaaS多租户,如何设计?

尼恩说在前面 在40岁老架构师 尼恩的读者交流群(50)中,最近有小伙伴拿到了一线互联网企业网易、美团、字节、如阿里、滴滴、极兔、有赞、希音、百度、美团的面试资格,遇到很多很重要的面试题: 多租户设计,如何 技术选型&#xff…

Mac中Finder是什么?怎么打开?

很多人都知道windows系统中的资源管理器,不过不知道什么是finder。finder和资源管理器一样,都是用来管理文件,finder存在于mac统中,那么finder有什么作用呢?下面下班就为大家分享关于mac系统中finder的相关内容。   1、怎么打开…

phpstudy页面不存在_网站的404页面对于SEO的重要作用

随着网站建设的需求和要求越来越多,网站的新形式也逐渐成为人们改版的方向,但是在网站的改版中难免会出现一些小差错,导致网站的运行不顺畅,这很有可能就是网站建设中忘记设计404页面,那么4040页面能给网站带来哪些好处…

计算机系统基础:虚拟存储管理知识笔记

1、虚拟存储管理概念 一个计算机任务只需要部分装入主存便可以启动运行,其余部分留在磁盘上,在需要的时候装入主存,这样可以提高主存空间的利用率。这样该系统所具有的主存容量会比实际主存容量大很多,这样的存储器称为虚拟存储器…

git推送指令配置_git 常用命令

git 简介在实际开发中,会使用git作为版本控制工具来完成团队协作。因此,对基本的git操作指令进行总结是十分有必要的,本文对一些术语或者理论基础,不重新码字,可以参考廖雪峰老师的博文,本文只对命令做归纳…

传统的线性降维方法效果不佳。_机器学习西瓜书简明笔记(11)降维与度量学习...

上篇主要介绍了几种常用的聚类算法,首先从距离度量与性能评估出发,列举了常见的距离计算公式与聚类评价指标,接着分别讨论了K-Means、LVQ、高斯混合聚类、密度聚类以及层次聚类算法。K-Means与LVQ都试图以类簇中心作为原型指导聚类&#xff0…

计算机系统基础:设备管理知识笔记

1、设备管理介绍 设备管理主要包括设备分配、缓冲区管理、实际物理I/O设备操作、通过管理提高设备利用率和方便用户使用的目的。 设备属于计算机系统和外界交互的工具,不要负责计算机和外部的输入/输出工作,通常称为外设。 2、设备分类 2.1 按数据组织分…

灌篮高手微信登录是什么服务器,灌篮高手微信登录版本

这款《灌篮高手》手游游戏是由同名的火爆动漫改写而成的,里边的游戏角色都是有极致的复原和保存,足球运动员特点都是有一定的展现。也有经典的动漫故事情节和每个高等院校足球队的复原。现阶段为大伙儿出示的是灌篮高手微信登录版本,能够和小…

华为发布岳云鹏手机_刚刚,华为发布鸿蒙2.0!手机可用!

不凡的2020年激动人心的时刻终于到来今天下午3时华为开发者大会2020在正式开幕鸿蒙2.0发布!本次大会包含主题演讲、技术论坛、松湖对话、Codelabs、Teach.Hour、互动体验等系列环节,大会将持续3天,众多活动也将于线上同步直播。技术论坛环节在…