2026/5/13 19:57:37
网站建设
项目流程
淄博建网站多少钱,网络营销策略包括哪几大策略,wordpress头像代码,网站源码上传安装包幂等性介绍现如今很多系统都会基于分布式或微服务思想完成对系统的架构设计。那么在这一个系统中#xff0c;就会存在若干个微服务#xff0c;而且服务间也会产生相互通信调用。那么既然产生了服务调用#xff0c;就必然会存在服务调用延迟或失败的问题。当出现这种问题就会存在若干个微服务而且服务间也会产生相互通信调用。那么既然产生了服务调用就必然会存在服务调用延迟或失败的问题。当出现这种问题服务端会进行重试等操作或客户端有可能会进行多次点击提交。如果这样请求多次的话那最终处理的数据结果就一定要保证统一如支付场景。此时就需要通过保证业务幂等性方案来完成幂等性不仅仅只是一次或多次操作对资源没有产生影响还包括第一次操作产生影响后以后多次操作不会再产生影响。并且幂等关注的是是否对资源产生影响而不关注结果。以SQL为例select * from table where id1此SQL无论执行多少次虽然结果有可能出现不同都不会对数据产生改变具备幂等性。insert into table(id,name) values(1,heima) 。此SQL如果id或name有唯一性约束多次操作只允许插入一条记录则具备幂等性。如果不是则不具备幂等性多次操作会产生多条数据。update table set score100 where id 1 。此SQL无论执行多少次对数据产生的影响都是相同的。具备幂等性。幂等性设计主要从两个维度进行考虑空间、时间空间定义了幂等的范围如生成订单的话不允许出现重复下单。时间定义幂等的有效期。有些业务需要永久性保证幂等如下单、支付等。而部分业务只要保证一段时间幂等即可。同时对于幂等的使用一般都会伴随着出现锁的概念用于解决并发安全问题。业务问题抛出在业务开发与分布式系统设计中幂等性是一个非常重要的概念有非常多的场景需要考虑幂等性的问题尤其对于现在的分布式系统经常性的考虑重试、重发等操作一旦产生这些操作则必须要考虑幂等性问题。以交易系统、支付系统等尤其明显如当用户购物进行下单操作用户操作多次但订单系统对于本次操作只能产生一个订单。当用户对订单进行付款支付系统不管出现什么问题应该只对用户扣一次款。当支付成功对库存扣减时库存系统对订单中商品的库存数量也只能扣减一次。当对商品进行发货时也需保证物流系统有且只能发一次货。在电商系统中还有非常多的场景需要保证幂等性。但是一旦考虑幂等后服务逻辑务必会变的更加复杂。因此是否要考虑幂等需要根据具体业务场景具体分析。而且在实现幂等时还会把并行执行的功能改为串行化降低了执行效率。此处以下单减库存为例当用户生成订单成功后会对订单中商品进行扣减库存。 订单服务会调用库存服务进行库存扣减。库存服务会完成具体扣减实现。现在对于功能调用的设计有可能出现调用超时因为出现如网络抖动虽然库存服务执行成功了但结果并没有在超时时间内返回则订单服务也会进行重试。那就会出现问题stock对于之前的执行已经成功了只是结果没有按时返回。而订单服务又重新发起请求对商品进行库存扣减。 此时出现库存扣减两次的问题。对于这种问题就需要通过幂等性进行结果。HTTP协议语义幂等性HTTP协议有两种方式RESTFUL、SOA。现在对于WEB API更多的会使用RESTFUL风格定义。为了更好的完成接口语义定义HTTP对于常用的四种请求方式也定义了幂等性的语义。GET用于获取资源多次操作不会对数据产生影响具有幂等性。注意不是结果。POST用于新增资源对同一个URI进行两次POST操作会在服务端创建两个资源不具有幂等性。PUT用于修改资源对同一个URI进行多次PUT操作产生的影响和第一次相同具备幂等性。DELETE用于删除资源对同一个URI进行多次DELETE操作产生的影响和第一次相同具备幂等性。综上所述这些仅仅只是HTTP协议建议在基于RESTFUL风格定义WEB API时的语义并非强制性。同时对于幂等性的实现肯定是通过前端或服务端完成。接口幂等对于幂等的考虑主要解决两点前后端交互与服务间交互。这两点有时都要考虑幂等性的实现。从前端的思路解决的话主要有三种前端防重、PRG模式、Token机制。token机制通过token机制来保证幂等是一种非常常见的解决方案同时也适合绝大部分场景。该方案需要前后端进行一定程度的交互来完成。服务端提供获取token接口供客户端进行使用。服务端生成token后如果当前为分布式架构将token存放于redis中如果是单体架构可以保存在jvm缓存中。当客户端获取到token后会携带着token发起请求。服务端接收到客户端请求后首先会判断该token在redis中是否存在。如果存在则完成进行业务处理业务处理完成后再删除token。如果不存在代表当前请求是重复请求直接向客户端返回对应标识。但是现在有一个问题当前是先执行业务再删除token。在高并发下很有可能出现第一次访问时token存在完成具体业务操作。但在还没有删除token时客户端又携带token发起请求此时因为token还存在第二次请求也会验证通过执行具体业务操作。对于这个问题的解决方案的思想就是并行变串行。会造成一定性能损耗与吞吐量降低。第一种方案对于业务代码执行和删除token整体加线程锁。当后续线程再来访问时则阻塞排队。基于自定义业务流程实现Token机制核心代码如下Componentpublic class FeignInterceptor implements RequestInterceptor {Overridepublic void apply(RequestTemplate requestTemplate) {//传递令牌RequestAttributes requestAttributes RequestContextHolder.getRequestAttributes();if (requestAttributes ! null){HttpServletRequest request ((ServletRequestAttributes)requestAttributes).getRequest();if (request ! null){EnumerationString headerNames request.getHeaderNames();while (headerNames.hasMoreElements()){String headerName headerNames.nextElement();if (token.equals(headerName)){String headerValue request.getHeader(headerName);//传递tokenrequestTemplate.header(headerName,headerValue);}}}}}}服务幂等防重表对于防止数据重复提交还有一种解决方案就是通过防重表实现。防重表的实现思路也非常简单。首先创建一张表作为防重表同时在该表中建立一个或多个字段的唯一索引作为防重字段用于保证并发情况下数据只有一条。在向业务表中插入数据之前先向防重表插入如果插入失败则表示是重复数据。对于防重表的解决方案可能有人会说为什么不使用悲观锁。悲观锁在使用的过程中也是会发生死锁的。悲观锁是通过锁表的方式实现的。 假设现在一个用户A访问表A锁住了表A然后试图访问表B 另一个用户B访问表B锁住了表B然后试图访问表A。 这时对于用户A来说由于表B已经被用户B锁住了所以用户A必须等到用户B释放表B才能访问。 同时对于用户B来说由于表A已经被用户A锁住了所以用户B必须等到用户A释放表A才能访问。此时死锁就已经产生了。MySQL乐观锁selectinsert防重提交分布式锁消息幂等在系统中当使用消息队列时无论做哪种技术选型有很多问题是无论如何也不能忽视的如消息必达、消息幂等等。本章节以典型的RabbitMQ为例讲解如何保证消息幂等的可实施解决方案其他MQ选型均可参考。消息重试演示消息队列的消息幂等性主要是由MQ重试机制引起的。因为消息生产者将消息发送到MQ-Server后MQ-Server会将消息推送到具体的消息消费者。假设由于网络抖动或出现异常时MQ-Server根据重试机制就会将消息重新向消息消费者推送造成消息消费者多次收到相同消息造成数据不一致。在RabbitMQ中消息重试机制是默认开启的但只会在consumer出现异常时才会重复推送。在使用中异常的出现有可能是由于消费方又去调用第三方接口由于网络抖动而造成异常但是这个异常有可能是暂时的。所以当消费者出现异常可以让其重试几次如果重试几次后仍然有异常则需要进行数据补偿。数据补偿方案当重试多次后仍然出现异常则让此条消息进入死信队列最终进入到数据库中接着设置定时job查询这些数据进行手动补偿。1、修改consumer一方的配置文件# 消费者监听相关配置listener:simple:retry:# 开启消费者(程序出现异常)重试机制默认开启并一直重试enabled: true# 最大重试次数max‐attempts: 5# 重试间隔时间(毫秒)initial‐interval: 30002、 设置消费异常当consumer消息监听类中添加异常最终接受消息时可以发现消息在接收五次后最终出现异常消息幂等解决要保证消息幂等性的话其实最终要解决的就是保证多次操作造成的影响是相同的。那么其解决方案的思路与服务间幂等的思路其实基本都是一致的。消息防重表解决思路与服务间幂等的防重表一致。redis。利用redis防重。