分布式架构中的幂等性
一.断言:幂等性的数学表达:f(f(x))=f(x)。幂等性是系统接口对外的一种承诺。幂等性指的是,使用相同参数对同一资源重复调用某个接口的结果与调用一次的结果相同。幂等性的一个实现是,使你的接口必须返回0(成功),即使这时资源或动作已经停止并且无工作要完成。
二.电商常见问题:2.1.如何防范POST重复提交HTTPPOST操作既不是安全的,也不是幂等的(至少在HTTP规范里没有保证)。当我们因为反复刷新浏览器导致多次提交表单,多次发出同样的POST请求,导致远端服务器重复创建出了资源。所以,对于电商应用来说,第一对应的后端WebService一定要做到幂等性,第二服务器端收到POST请求,在操作成功后必须302跳转到另外一个页面,这样即使用户刷新页面,也不会重复提交表单。2.2.集群环境下的定时任务幂等性分布式环境下,定时任务或异步处理如何保持幂等性?
三.把分布式事务分解为具有幂等性的异步消息处理:电商的很多业务,考虑更多的是BASE(即BasicallyAvailable、Softstate、和Eventuallyconsistent),而不是ACID(Atomicity、Consistency、Isolation和Durability)。即为了满足高负载的用户访问,我们可以容忍短暂的数据不一致。那怎么做呢?第一,不做分布式事务,代价太大。第二,不一定需要实时一致性,只需要保证最终的一致性即可。第三,“通过状态机和严格的有序操作,来最大限度地降低不一致性”。第四,最终一致性(EventuallyConsistent)通过异步事件做到。如果消息具有操作幂等性,也就是一个消息被应用多次与应用一次产生的效果是一样的话,那么把不需要同步执行的事务交给异步消息推送和订阅者集群来处理即可。假如消息处理失败,那么就消息重播,由于幂等性,应用多次也能产生正确的结果。实际情况下,消息很难具有幂等性,解决方法是使用另一个表记录已经被成功应用的消息,即消息队列和消息应用状态表一起来解决问题。
参考资源:1)weidagang2046,博客园,理解HTTP幂等性;2)相关设计模式“SynchronizedToken(简而言之,就是客户端的每一次Request里,必须携带一个服务器端给出的HashCode作为Token,这个Token只能用一次,不能重复使用)”和“幂等接收器,IdempotentReceiver”;3)针对POST,请参考HTTPLR(由BilldehÓra提出)、MarkNottingham的POE(POSTOnceExactly)和PaulPrescod的HTTP中的可靠传递。(另一个值得一提的是YaronGoland的SOA-Rity);4)淘宝核心系统团队博客,2010,用消息队列和消息应用状态表来消除分布式事务
电商课题:RBAC权限控制电商课题VI:分布式Session电商课题:cookie防篡改电商课题V:分布式锁电商课题I:ThrottleLimitsforcalls/requestsinaclusteredenvironment
Todd.log-aplacetokeepmythoughtsonprogramming
理解HTTP幂等性基于HTTP协议的WebAPI是时下最为流行的一种分布式服务提供方式。无论是在大型互联网应用还是企业级架构中,我们都见到了越来越多的SOA或RESTful的WebAPI。为什么WebAPI如此流行呢?我认为很大程度上应归功于简单有效的HTTP协议。HTTP协议是一种分布式的面向资源的网络应用层协议,无论是服务器端提供Web服务,还是客户端消费Web服务都非常简单。再加上浏览器、Javascript、AJAX、JSON以及HTML5等技术和工具的发展,互联网应用架构设计表现出了从传统的PHP、JSP、ASP.NET等服务器端动态网页向WebAPI+RIA(富互联网应用)过渡的趋势。WebAPI专注于提供业务服务,RIA专注于用户界面和交互设计,从此两个领域的分工更加明晰。在这种趋势下,WebAPI设计将成为服务器端程序员的必修课。然而,正如简单的Java语言并不意味着高质量的Java程序,简单的HTTP协议也不意味着高质量的WebAPI。要想设计出高质量的WebAPI,还需要深入理解分布式系统及HTTP协议的特性。
幂等性定义本文所要探讨的正是HTTP协议涉及到的一种重要性质:幂等性(Idempotence)。在HTTP/1.1规范中幂等性的定义是:
Methodscanalsohavethepropertyof"idempotence"inthat(asidefromerrororexpirationissues)theside-effectsofN>0identicalrequestsisthesameasforasinglerequest.
从定义上看,HTTP方法的幂等性是指一次和多次请求某一个资源应该具有同样的副作用。幂等性属于语义范畴,正如编译器只能帮助检查语法错误一样,HTTP规范也没有办法通过消息格式等语法手段来定义它,这可能是它不太受到重视的原因之一。但实际上,幂等性是分布式系统设计中十分重要的概念,而HTTP的分布式本质也决定了它在HTTP中具有重要地位。
分布式事务vs幂等设计为什么需要幂等性呢?我们先从一个例子说起,假设有一个从账户取钱的远程API(可以是HTTP的,也可以不是),我们暂时用类函数的方式记为:
boolwithdraw(account_id,amount)withdraw的语义是从account_id对应的账户中扣除amount数额的钱;如果扣除成功则返回true,账户余额减少amount;如果扣除失败则返回false,账户余额不变。值得注意的是:和本地环境相比,我们不能轻易假设分布式环境的可靠性。一种典型的情况是withdraw请求已经被服务器端正确处理,但服务器端的返回结果由于网络等原因被掉丢了,导致客户端无法得知处理结果。如果是在网页上,一些不恰当的设计可能会使用户认为上一次操作失败了,然后刷新页面,这就导致了withdraw被调用两次,账户也被多扣了一次钱。如图1所示:
图1这个问题的解决方案一是采用分布式事务,通过引入支持分布式事务的中间件来保证withdraw功能的事务性。分布式事务的优点是对于调用者很简单,复杂性都交给了中间件来管理。缺点则是一方面架构太重量级,容易被绑在特定的中间件上,不利于异构系统的集成;另一方面分布式事务虽然能保证事务的ACID性质,而但却无法提供性能和可用性的保证。
另一种更轻量级的解决方案是幂等设计。我们可以通过一些技巧把withdraw变成幂等的,比如:
intcreate_ticket()boolidempotent_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所示:
图2和分布式事务相比,幂等设计的优势在于它的轻量级,容易适应异构环境,以及性能和可用性方面。在某些性能要求比较高的应用,幂等设计往往是唯一的选择。
HTTP的幂等性HTTP协议本身是一种面向资源的应用层协议,但对HTTP协议的使用实际上存在着两种不同的方式:一种是RESTful的,它把HTTP当成应用层协议,比较忠实地遵守了HTTP协议的各种规定;另一种是SOA的,它并没有完全把HTTP当成应用层协议,而是把HTTP协议作为了传输层协议,然后在HTTP之上建立了自己的应用层协议。本文所讨论的HTTP幂等性主要针对RESTful风格的,不过正如上一节所看到的那样,幂等性并不属于特定的协议,它是分布式系统的一种特性;所以,不论是SOA还是RESTful的WebAPI设计都应该考虑幂等性。下面将介绍HTTPGET、DELETE、PUT、POST四种主要方法的语义和幂等性。
HTTPGET方法用于获取资源,不应有副作用,所以是幂等的。比如:GEThttp://www.bank.com/account/123456,不会改变资源的状态,不论调用一次还是N次都没有副作用。请注意,这里强调的是一次和N次具有相同的副作用,而不是每次GET的结果相同。GEThttp://www.news.com/latest-news这个HTTP请求可能会每次得到不同的结果,但它本身并没有产生任何副作用,因而是满足幂等性的。
HTTPDELETE方法用于删除资源,有副作用,但它应该满足幂等性。比如:DELETEhttp://www.forum.com/article/4231,调用一次和N次对系统产生的副作用是相同的,即删掉id为4231的帖子;因此,调用者可以多次调用或刷新页面而不必担心引起错误。
比较容易混淆的是HTTPPOST和PUT。POST和PUT的区别容易被简单地误认为“POST表示创建资源,PUT表示更新资源”;而实际上,二者均可用于创建资源,更为本质的差别是在幂等性方面。在HTTP规范中对POST和PUT是这样定义的:
ThePOSTmethodisusedtorequestthattheoriginserveraccepttheentityenclosedintherequestasanewsubordinateoftheresourceidentifiedbytheRequest-URIintheRequest-Line......Ifaresourcehasbeencreatedontheoriginserver,theresponseSHOULDbe201(Created)andcontainanentitywhichdescribesthestatusoftherequestandreferstothenewresource,andaLocationheader.
接口的幂等性
接⼝的幂等性接⼝幂等性问题,对于开发⼈员来说,是⼀个跟语⾔⽆关的公共问题。
本⽂分享了⼀些解决这类问题⾮常实⽤的办法,绝⼤部分内容我在项⽬中实践过的,给有需要的⼩伙伴⼀个参考。
不知道你有没有遇到过这些场景:1.有时我们在填写某些form表单时,保存按钮不⼩⼼快速点了两次,表中竟然产⽣了两条重复的数据,只是id不⼀样。
2.我们在项⽬中为了解决接⼝超时问题,通常会引⼊了重试机制。
第⼀次请求接⼝超时了,请求⽅没能及时获取返回结果(此时有可能已经成功了),为了避免返回错误的结果(这种情况不可能直接返回失败吧?),于是会对该请求重试⼏次,这样也会产⽣重复的数据。
3.mq消费者在读取消息时,有时候会读取到重复消息,如果处理不好,也会产⽣重复的数据。
这些都是幂等性问题。
接⼝幂等性是指⽤户对于同⼀操作发起的⼀次请求或者多次请求的结果是⼀致的,不会因为多次点击⽽产⽣了副作⽤。
这类问题多发于接⼝的:insert操作,这种情况下多次请求,可能会产⽣重复数据。
update操作,如果只是单纯的更新数据,⽐如:update user set status=1 where id=1,是没有问题的。
如果还有计算,⽐如:update user set status=status+1 where id=1,这种情况下多次请求,可能会导致数据错误。
那么我们要如何保证接⼝幂等性?⼀. insert前先select通常情况下,在保存数据的接⼝中,我们为了防⽌产⽣重复数据,⼀般会在insert前,先根据name或code字段select⼀下数据。
如果该数据已存在,则执⾏update操作,如果不存在,才执⾏insert操作。
该⽅案可能是我们平时在防⽌产⽣重复数据时,使⽤最多的⽅案。
但是该⽅案不适⽤于并发场景,在并发场景中,要配合其他⽅案⼀起使⽤,否则同样会产⽣重复数据。
我在这⾥提⼀下,是为了避免⼤家踩坑。
⼆.加乐观锁需要在表中增加⼀个timestamp或者version字段,这⾥以version字段为例。
idempotence注解
idempotence注解
在软件开发中,幂等性是一个重要的概念,它表示一个操作不论执行多少次,其结果都是相同的。
在RESTful API设计中,幂等性也是一个重要的考虑因素。
通过使用idempotence 注解,我们可以告诉客户端和服务器这个操作是幂等的,从而保证操作的可靠性和一致性。
在Java中,我们可以使用Spring框架提供的`@Idempotent`注解来标记一个方法为幂等的。
当一个HTTP请求被标记为幂等时,该请求可以安全地被重试而不会导致重复的副作用。
这在使用网络不稳定或可能出现暂时性故障的情况下非常有用,因为它可以保证操作的可靠性和一致性。
使用`@Idempotent`注解的方法应该返回一个HTTP状态码,表示该请求是否已经被成功处理。
如果请求已经被处理过,则应该返回200 OK状态码;如果请求未被处理过,则应该返回201 Created状态码。
这样,客户端可以根据返回的状态码来判断是否需要重试该请求。
总之,idempotence注解是RESTful API设计中一个重要的概念,它可以保证操作的可靠性和一致性。
通过使用`@Idempotent`注解,我们可以告诉客户端和服务器这个操作是幂等的,从而避免重复的副作用和数据不一致的问题。
1。
seata分布式事务--TCC模式
seata分布式事务--TCC模式基本概念:TCC(Try-Confirm-Cancel)分布式事务模型相对于 XA 等传统模型,其特征在于它不依赖 RM 对分布式事务的⽀持,⽽是通过对业务逻辑的分解来实现分布式事务。
TCC与AT模式相同,也是⼆阶段提交,但是TCC对业务代码侵⼊性很强TCC模式下,所有事务都要⼿动实现Try,Confirm,Cancel三个⽅法TCC 模型认为对于业务系统中⼀个特定的业务逻辑,其对外提供服务时,必须接受⼀些不确定性,即对业务逻辑初步操作的调⽤仅是⼀个临时性操作,调⽤它的主业务服务保留了后续的取消权。
如果主业务服务认为全局事务应该回滚,它会要求取消之前的临时性操作,这就对应从业务服务的取消操作。
⽽当主业务服务认为全局事务应该提交时,它会放弃之前临时性操作的取消权,这对应从业务服务的确认操作。
每⼀个初步操作,最终都会被确认或取消。
因此,针对⼀个具体的业务服务,TCC 分布式事务模型需要业务系统提供三段业务逻辑:1. 初步操作 Try:完成所有业务检查,预留必须的业务资源。
2. 确认操作 Confirm:真正执⾏的业务逻辑,不做任何业务检查,只使⽤ Try 阶段预留的业务资源。
因此,只要 Try 操作成功,Confirm 必须能成功。
另外,Confirm 操作需满⾜幂等性,保证⼀笔分布式事务能且只能成功⼀次。
3. 取消操作 Cancel:释放 Try 阶段预留的业务资源。
同样的,Cancel 操作也需要满⾜幂等性。
⼯作机制:⼀阶段TMTM处理流程和AT模式下⼀样:1.开启全局事务,向TC注册全局事务并返回XID2.如果业务执⾏成功,通知TC全局事务提交3.如果业务执⾏失败,通知TC全局事务回滚4.清除内存中XIDRM注册分⽀事务,获取branchId。
并将⽅法调⽤时的上下⽂发送给TC。
执⾏业务逻辑⼆阶段TMTM通知TC全局提交/回滚。
TC通知各分⽀事务。
RM处理消息逻辑是RMHandlerTCC⾥。
java分布式事务tcc的实现方法
java分布式事务tcc的实现方法Java分布式事务TCC实现方法详解随着互联网的快速发展,分布式系统越来越普遍,而分布式系统在面对数据一致性、事务处理与性能等方面遇到了许多问题。
在解决这些问题中,事务是不可避免的一个方面。
本文将介绍Java分布式事务TCC的实现方法,旨在帮助读者更好地理解该技术。
一、什么是Java分布式事务TCC?TCC,全称为“Try-Confirm-Cancel”,即“尝试-确认-撤销”模型。
它是一种实现分布式事务的方式,可以保证分布式事务的ACID特性(原子性、一致性、隔离性和持久性),并减少数据冲突的概率,提高了系统的可用性和容错性。
Java分布式事务TCC的实现基于该模型,它利用三个阶段协调远程的服务调用,来达到分布式事务的控制和管理。
二、Java分布式事务TCC的实现方法1. Try阶段:在这个阶段中,调用方准备将分布式事务的操作,在本地事务中执行。
同时,它也负责向远程服务发出执行请求。
2. Confirm阶段:在Try阶段成功执行的情况下,远程的服务将会执行相应的操作,并在Confirm阶段对事务进行确认。
如果确认成功,事务就会被提交,否则会被回滚。
3. Cancel阶段:在Try阶段未能成功执行的情况下,远程的服务将什么也不做。
而在Confirm阶段失败的情况下,远程的服务将会执行事务回滚操作。
Java分布式事务TCC的实现方法需要保证以下约束:(1)Cancel阶段的执行安全性。
(2)Confirm阶段的幂等性。
(3)Try和Confirm阶段的数据一致性。
三、实现Java分布式事务TCC的框架1. FescarFescar是阿里巴巴分布式事务中间件,支持TCC等分布式事务模型,可以保证ACID特性。
它是一个高性能、易扩展的分布式事务解决方案,适用于云原生的架构,在淘宝、支付宝、菜鸟等众多项目中得到了广泛应用。
2. HmilyHmily是国内另一个优秀的分布式事务框架,它采用TCC模型实现分布式事务,通过拦截方法调用实现TCC事务的切入和控制,使用注解方法简化编程,较好地解决了分布式事务问题。
分布式数据系统的数据采集方法及分布式数据系统
分布式数据系统的数据采集方法及分布式数据系统引言概述:分布式数据系统是现代大数据处理的核心组成部份,其能够高效地处理海量数据并保证数据的可靠性和一致性。
而数据采集是分布式数据系统中至关重要的一环,本文将详细介绍分布式数据系统的数据采集方法及其在分布式数据系统中的应用。
一、数据采集方法1.1 传统数据采集方法传统数据采集方法主要包括手动输入、文件导入和数据库连接。
手动输入是最基本的数据采集方法,适合于数据量较少的情况;文件导入则是通过将数据存储在文件中,再导入到系统中进行处理;数据库连接是通过连接数据库,直接从数据库中获取数据。
这些方法简单易用,但效率较低,无法满足大规模数据采集的需求。
1.2 自动化数据采集方法自动化数据采集方法通过使用自动化工具和技术,实现数据的自动采集和处理。
其中,网络爬虫是一种常用的自动化数据采集方法,通过摹拟浏览器行为,自动访问网页并提取数据。
此外,还有基于API的数据采集方法,通过调用API接口获取数据。
这些方法能够实现大规模数据采集,但对于分布式数据系统来说,需要考虑数据的分布和并行处理能力。
1.3 流式数据采集方法流式数据采集方法是一种实时采集数据的方式,能够实时地处理数据流。
常见的流式数据采集方法包括消息队列和流处理引擎。
消息队列通过将数据存储在队列中,实现数据的异步传输和处理;流处理引擎则是通过实时处理数据流,将数据分发到不同的节点进行处理。
这些方法适合于需要实时处理数据的场景,但对于分布式数据系统来说,需要考虑数据的分布和负载均衡等问题。
二、分布式数据系统中的数据采集2.1 数据采集的并行处理在分布式数据系统中,数据采集需要考虑数据的分布和并行处理能力。
通过将数据划分为多个分片,并将分片分发到不同的节点进行处理,可以实现数据的并行采集和处理。
同时,还需要考虑数据的负载均衡,确保每一个节点的负载均衡。
2.2 数据采集的数据一致性在分布式数据系统中,数据一致性是一个重要的问题。
分布式架构设计概要总结
分布式架构设计概要总结一、构建分布式的原因——业务架构的演进分布式系统,顾名思义,数据是分布在不同的节点上,那么数据分布就是首先需要考虑的一点。
我们先思考几点:1、数据如何均匀分布到不同的节点上,涉及到负载均衡;2、为了保证数据的可靠些,需要对数据设置多个副本,那么如何保证副本之间的一致性;3、节点是廉价的pc机,如果节点宕机,那么如何自动检测,并迁移数据;4、分布式最基础的两个协议,一个是paxos选举协议,一个是两阶段提交协议:●paxos选举协议:用于在多个节点中选举一个总控节点;●两阶段提交协议:保证在多个节点中事务操作的原子性,要么完全成功,要么全部失败。
在上图简单以时间线为准,粗略描述了我们系统架构随着业务的需求考量以及业务的发展,系统承担的并发量也将逐步提升,这就要求我们的系统架构需要开始思考如何利用现有的资源来解决。
我们目前急需处理并发请求的服务.而思考的方向可以从我们已有的计算机知识体系中找到答案。
比如:●对于并发问题,我们知道处理共享资源可以通过加锁的方式来保证我们的线程安全,那么在有限的资源下又要如何提升我们的并发量,于是我们很容易想到hashmap是如何处理线程安全的,对此我们就会考虑到一个设计思想,那就是分而治之的策略,即是否可以将共享资源拆分成多份来缓解我们的压力,即集群.●这个时候我们的流量压力通过集群分担到各个应用中,但是此时对数据库的压力反而增加了,于是我们会想到使用缓存策略来缓解我们的压力,对于缓存架构,我们也可以采用CPU高速缓存的策略来对我们现有的服务进行改进。
●另外,随着业务的增长以及需求不断地调整变化,有时候为了提升我们的查询性能,还需要以不同的维度重新构建数据库表结构。
比如订单服务,可以以用户维护进行数据异构产生用户与订单服务的数据库表结构来提升我们的查询性能。
其实对于这种数据异构在编程设计中也是有体现的,比如表单的业务 bean 与数据库存储的业务 bean 多少存在一些冗余但可能是类型或者是状态显示不同,目的当然是简化便于理解。
