当前位置: 首页 > news >正文

建设机械网站哪家好wordpress怎么用vue

建设机械网站哪家好,wordpress怎么用vue,青岛网站建设服务平台,用什么做网站开发一、什么是幂等性 简单来说#xff0c;就是对一个接口执行重复的多次请求#xff0c;与一次请求所产生的结果是相同的#xff0c;听起来非常容易理解#xff0c;但要真正的在系统中要始终保持这个目标#xff0c;是需要很严谨的设计的#xff0c;在实际的生产环境下就是对一个接口执行重复的多次请求与一次请求所产生的结果是相同的听起来非常容易理解但要真正的在系统中要始终保持这个目标是需要很严谨的设计的在实际的生产环境下我们应该保证任何接口都是幂等的而如何正确的实现幂等就是本文要讨论的内容。 二、哪些请求天生就是幂等的 首先我们要知道查询类的请求一般都是天然幂等的除此之外删除请求在大多数情况下也是幂等的但是ABA场景下除外。 举一个简单的例子 比如先请求了一次删除A的操作但由于响应超时又自动请求了一次删除A的操作如果在两次请求之间又插入了一次A而实际上新插入的这一次A是不应该被删除的这就是ABA问题不过在大多数业务场景中ABA问题都是可以忽略的。 除了查询和删除之外还有更新操作同样的更新操作在大多数场景下也是天然幂等的其例外是也会存在ABA的问题更重要的是比如执行update table set a a 1 where v 1这样的更新就非幂等了。 最后就还剩插入了插入大多数情况下都是非幂等的除非是利用数据库唯一索引来保证数据不会重复产生。 三、为什么需要幂等 1.超时重试 当发起一次RPC请求时难免会因为网络不稳定而导致请求失败一般遇到这样的问题我们希望能够重新请求一次正常情况下没有问题但有时请求实际上已经发出去了只是在请求响应时网络异常或者超时此时请求方如果再重新发起一次请求那被请求方就需要保证幂等了。 2.异步回调 异步回调是提升系统接口吞吐量的一种常用方式很明显此类接口一定是需要保证幂等性的。 3.消息队列 现在常用的消息队列框架比如Kafka、RocketMQ、RabbitMQ在消息传递时都会采取At least once原则也就是至少一次原则在消息传递时不允许丢消息但是允许有重复的消息既然消息队列不保证不会出现重复的消息那消费者自然要保证处理逻辑的幂等性了。 四、实现幂等的关键因素 关键因素1 幂等唯一标识可以叫它幂等号或者幂等令牌或者全局ID总之就是客户端与服务端一次请求时的唯一标识一般情况下由客户端来生成也可以让第三方来统一分配。 关键因素2 有了唯一标识以后服务端只需要确保这个唯一标识只被使用一次即可一种常见的方式就是利用数据库的唯一索引。 五、注解实现幂等性 定义DistributedLock注解 Target({ElementType.METHOD}) Retention(RetentionPolicy.RUNTIME) Documented public interface DistributedLock {/*** 保证业务接口的key的唯一性否则失去了分布式锁的意义 锁key* 支持使用spEl表达式*/String key();/*** 保证业务接口的key的唯一性否则失去了分布式锁的意义 锁key 前缀*/String keyPrefix() default ;/*** 是否在等待时间内获取锁如果在等待时间内无法获取到锁则返回失败*/boolean tryLok() default false;/*** 获取锁的最大尝试时间 会尝试tryTime时间获取锁在该时间内获取成功则返回否则抛出获取锁超时异常tryLoktrue时该值必须大于0。**/long tryTime() default 0;/*** 加锁的时间超过这个时间后锁便自动解锁*/long lockTime() default 30;/*** tryTime 和 lockTime的时间单位*/TimeUnit unit() default TimeUnit.SECONDS;/*** 是否公平锁false:非公平锁true:公平锁*/boolean fair() default false; } 定义DistributedLockAspect Lock切面 Aspect Slf4j public class DistributedLockAspect {Resourceprivate IDistributedLock distributedLock;/*** SpEL表达式解析*/private SpelExpressionParser spelExpressionParser new SpelExpressionParser();/*** 用于获取方法参数名字*/private DefaultParameterNameDiscoverer nameDiscoverer new DefaultParameterNameDiscoverer();Pointcut(annotation(com.yt.bi.common.redis.distributedlok.annotation.DistributedLock))public void distributorLock() {}Around(distributorLock())public Object around(ProceedingJoinPoint pjp) throws Throwable {// 获取DistributedLockDistributedLock distributedLock this.getDistributedLock(pjp);// 获取 lockKeyString lockKey this.getLockKey(pjp, distributedLock);ILock lockObj null;try {// 加锁tryLok true,并且tryTime 0时尝试获取锁获取不到超时异常if (distributedLock.tryLok()) {if(distributedLock.tryTime() 0){throw new IdempotencyException(tryTime must be greater than 0);}lockObj this.distributedLock.tryLock(lockKey, distributedLock.tryTime(), distributedLock.lockTime(), distributedLock.unit(), distributedLock.fair());} else {lockObj this.distributedLock.lock(lockKey, distributedLock.lockTime(), distributedLock.unit(), distributedLock.fair());}if (Objects.isNull(lockObj)) {throw new IdempotencyException(Duplicate request for method still in process);}return pjp.proceed();} catch (Exception e) {throw e;} finally {// 解锁this.unLock(lockObj);}}/*** param pjp* return* throws NoSuchMethodException*/private DistributedLock getDistributedLock(ProceedingJoinPoint pjp) throws NoSuchMethodException {String methodName pjp.getSignature().getName();Class clazz pjp.getTarget().getClass();Class?[] par ((MethodSignature) pjp.getSignature()).getParameterTypes();Method lockMethod clazz.getMethod(methodName, par);DistributedLock distributedLock lockMethod.getAnnotation(DistributedLock.class);return distributedLock;}/*** 解锁** param lockObj*/private void unLock(ILock lockObj) {if (Objects.isNull(lockObj)) {return;}try {this.distributedLock.unLock(lockObj);} catch (Exception e) {log.error(分布式锁解锁异常, e);}}/*** 获取 lockKey** param pjp* param distributedLock* return*/private String getLockKey(ProceedingJoinPoint pjp, DistributedLock distributedLock) {String lockKey distributedLock.key();String keyPrefix distributedLock.keyPrefix();if (StringUtils.isBlank(lockKey)) {throw new IdempotencyException(Lok key cannot be empty);}if (lockKey.contains(#)) {this.checkSpEL(lockKey);MethodSignature methodSignature (MethodSignature) pjp.getSignature();// 获取方法参数值Object[] args pjp.getArgs();lockKey getValBySpEL(lockKey, methodSignature, args);}lockKey StringUtils.isBlank(keyPrefix) ? lockKey : keyPrefix lockKey;return lockKey;}/*** 解析spEL表达式** param spEL* param methodSignature* param args* return*/private String getValBySpEL(String spEL, MethodSignature methodSignature, Object[] args) {// 获取方法形参名数组String[] paramNames nameDiscoverer.getParameterNames(methodSignature.getMethod());if (paramNames null || paramNames.length 1) {throw new IdempotencyException(Lok key cannot be empty);}Expression expression spelExpressionParser.parseExpression(spEL);// spring的表达式上下文对象EvaluationContext context new StandardEvaluationContext();// 给上下文赋值for (int i 0; i args.length; i) {context.setVariable(paramNames[i], args[i]);}return expression.getValue(context).toString();}/*** SpEL 表达式校验** param spEL* return*/private void checkSpEL(String spEL) {try {ExpressionParser parser new SpelExpressionParser();parser.parseExpression(spEL, new TemplateParserContext());} catch (Exception e) {log.error(spEL表达式解析异常, e);throw new IdempotencyException(Invalid SpEL expression [ spEL ]);}} } 定义分布式锁注解版启动元注解 Target(ElementType.TYPE) Retention(RetentionPolicy.RUNTIME) Documented Import({DistributedLockAspect.class}) public interface EnableDistributedLock { } 定义IDistributedLock分布式锁接口 public interface IDistributedLock {/*** 获取锁默认30秒失效失败一直等待直到获取锁** param key 锁的key* return 锁对象*/ILock lock(String key);/*** 获取锁,失败一直等待直到获取锁** param key 锁的key* param lockTime 加锁的时间超过这个时间后锁便自动解锁 如果lockTime为-1则保持锁定直到显式解锁* param unit {code lockTime} 参数的时间单位* param fair 是否公平锁* return 锁对象*/ILock lock(String key, long lockTime, TimeUnit unit, boolean fair);/*** 尝试获取锁30秒获取不到超时异常锁默认30秒失效** param key 锁的key* param tryTime 获取锁的最大尝试时间* return* throws Exception*/ILock tryLock(String key, long tryTime) throws Exception;/*** 尝试获取锁获取不到超时异常** param key 锁的key* param tryTime 获取锁的最大尝试时间* param lockTime 加锁的时间* param unit {code tryTime code lockTime} 参数的时间单位* param fair 是否公平锁* return* throws Exception*/ILock tryLock(String key, long tryTime, long lockTime, TimeUnit unit, boolean fair) throws Exception;/*** 解锁** param lock* throws Exception*/void unLock(Object lock);/*** 释放锁** param lock* throws Exception*/default void unLock(ILock lock) {if (lock ! null) {unLock(lock.getLock());}}} IDistributedLock实现类 Slf4j Component public class RedissonDistributedLock implements IDistributedLock {Resourceprivate RedissonClient redissonClient;/*** 统一前缀*/Value(${redisson.lock.prefix:bi:distributed:lock})private String prefix;Overridepublic ILock lock(String key) {return this.lock(key, 0L, TimeUnit.SECONDS, false);}Overridepublic ILock lock(String key, long lockTime, TimeUnit unit, boolean fair) {RLock lock getLock(key, fair);// 获取锁,失败一直等待,直到获取锁,不支持自动续期if (lockTime 0L) {lock.lock(lockTime, unit);} else {// 具有Watch Dog 自动延期机制 默认续30s 每隔30/310 秒续到30slock.lock();}return new ILock(lock, this);}Overridepublic ILock tryLock(String key, long tryTime) throws Exception {return this.tryLock(key, tryTime, 0L, TimeUnit.SECONDS, false);}Overridepublic ILock tryLock(String key, long tryTime, long lockTime, TimeUnit unit, boolean fair)throws Exception {RLock lock getLock(key, fair);boolean lockAcquired;// 尝试获取锁获取不到超时异常,不支持自动续期if (lockTime 0L) {lockAcquired lock.tryLock(tryTime, lockTime, unit);} else {// 具有Watch Dog 自动延期机制 默认续30s 每隔30/310 秒续到30slockAcquired lock.tryLock(tryTime, unit);}if (lockAcquired) {return new ILock(lock, this);}return null;}/*** 获取锁** param key* param fair* return*/private RLock getLock(String key, boolean fair) {RLock lock;String lockKey prefix : key;if (fair) {// 获取公平锁lock redissonClient.getFairLock(lockKey);} else {// 获取普通锁lock redissonClient.getLock(lockKey);}return lock;}Overridepublic void unLock(Object lock) {if (!(lock instanceof RLock)) {throw new IllegalArgumentException(Invalid lock object);}RLock rLock (RLock) lock;if (rLock.isLocked()) {try {rLock.unlock();} catch (IllegalMonitorStateException e) {log.error(释放分布式锁异常, e);}}} } 定义ILock锁对象 import lombok.AllArgsConstructor; import lombok.Getter;import java.util.Objects;/*** p* RedissonLock 包装的锁对象 实现AutoCloseable接口在java7的try(with resource)语法不用显示调用close方法* /p* since 2023-06-08 16:57*/ AllArgsConstructor public class ILock implements AutoCloseable {/*** 持有的锁对象*/Getterprivate Object lock;/*** 分布式锁接口*/Getterprivate IDistributedLock distributedLock;Overridepublic void close() throws Exception {if(Objects.nonNull(lock)){distributedLock.unLock(lock);}} } 六、使用示例  启动类添加EnableDistributedLock启用注解支持 SpringBootApplication EnableDistributedLock public class BiCenterGoodsApplication {public static void main(String[] args) {SpringApplication.run(BiCenterGoodsApplication.class, args);} } DistributedLock标注需要使用分布式锁的方法  ApiOperation(编辑SKU供应商供货信息)PostMapping(/editSupplierInfo)//DistributedLock(key #dto.sku - #dto.skuId, lockTime 10L, keyPrefix sku-)DistributedLock(key #dto.sku, lockTime 10L, keyPrefix sku-)public RBoolean editSupplierInfo(RequestBody Validated ProductSkuSupplierInfoDTO dto) {return R.ok(productSkuSupplierMeasureService.editSupplierInfo(dto));} #dto.sku是 SpEL表达式。Spring中支持的它都支持的。比如调用静态方法三目表达式。SpEL 可以使用方法中的任何参数。SpEL表达式参考 从原理到实践分析 Redis 分布式锁的多种实现方案一 从原理到实践分析 Redisson 分布式锁的实现方案二 Spring Boot 集成 Redisson分布式锁 参考文章一个注解优雅的实现接口幂等性
http://www.sczhlp.com/news/154047/

相关文章:

  • 哪个网站是营销型网站网站封装成app可以做热更新
  • 视频弹幕网站建设网页制作作业源代码
  • dw怎么做网站教程新闻系统网站开发dw实训总结报告
  • 常德做网站建设的公司奇客影院wordpress
  • 如何网站推广宣传怎么查找网站备案主体
  • 做网站必须要买服务器吗wordpress 文章首标点
  • 年轻人常用网站浏览有关小城镇建设的网站 记录
  • 南昌建设网站公司没有版权可以做视频网站吗
  • DailyPaper-2025-9-30
  • Powershell 管理 后台/计划 作业(六)
  • 32. 最长有效括号
  • 网站托管服务 优帮云大数据技术是学什么的
  • 丰都网站jsp网站开发的参考文献
  • 地下彩票网站建设誉重网站建设案例
  • 那种导航网站重庆建工集团股份有限公司官网
  • 小语种外贸网站有哪些做短租的网站
  • java17及以上版本如何抵御TemplatesImpl注入
  • 龙岗网站建设企业查网站是否正规
  • jsp mysql 网站开发昆明小程序开发多少钱
  • 郑州品牌网站建设费用微信会员卡管理系统怎么开通
  • 做爰全过程免费的视频的网站平面设计画册设计
  • apache网站部署高端网页开发
  • 江西网站做的好的企业90平方设计
  • 衡水手机网站建设网络推广产品
  • 食品网站app建设医院网站建设
  • 建个网站需要多少钱微信crm
  • 黄浦集团网站建设哈尔滨自助板建站
  • 广西住房和城乡建设门户网站电商企业网站源码
  • 详细介绍:【C++实战(53)】C++11线程库:开启多线程编程新世界
  • 网站开发方案设计好的优化网站推广公司