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

制作购物网站需要多少钱百度网页版主页网址

制作购物网站需要多少钱,百度网页版主页网址,综合b2b平台有哪些,wordpress 源码下载背景 在学校的Java项目中,开发了一个文本聊天的api接口,由于当时考虑欠缺,加上调用方没有做限制,导致出现了一个用户在一秒内重复发出了多次请求的情况,从而出现了脏数据。 既然是接口重复请求了,那么就…

背景
    在学校的Java项目中,开发了一个文本聊天的api接口,由于当时考虑欠缺,加上调用方没有做限制,导致出现了一个用户在一秒内重复发出了多次请求的情况,从而出现了脏数据。


既然是接口重复请求了,那么就需要限制一个用户在一秒内只能发起一次请求。这时候就会引出一个概念【接口的幂等性】。
幂等性, 通俗的说就是一个接口, 多次发起同一个请求, 必须保证操作只能执行一次。
现实的场景如下

1. ​​订单与支付类操作​

  • ​订单创建​​:用户多次点击提交订单,需保证仅生成一个有效订单。
  • ​订单支付​​:支付接口因网络超时重试时,需确保扣款仅一次,避免重复扣款。
  • ​订单状态变更​​:如订单发货、完成等操作,重复请求需维持最终状态一致。

​示例​​:
用户支付时因网络延迟重复调用支付接口,若未做幂等,可能生成两笔扣款记录。


2. ​​资源分配与扣减​

  • ​库存扣减​​:秒杀场景中,多次请求需确保库存不被超卖。
  • ​优惠券/积分发放​​:用户领取优惠券或积分时,需防止重复领取。
  • ​账号注册​​:同一手机号或邮箱多次注册,需返回已存在的结果。

​示例​​:
库存扣减时,若重复扣减未校验幂等性,可能导致库存变为负数。


接口幂等性主要应用于 ​​可能因重复请求导致数据错误或资源冲突​​ 的业务场景,以下是典型业务操作分类:


1. ​​订单与支付类操作​

  • ​订单创建​​:用户多次点击提交订单,需保证仅生成一个有效订单。
  • ​订单支付​​:支付接口因网络超时重试时,需确保扣款仅一次,避免重复扣款。
  • ​订单状态变更​​:如订单发货、完成等操作,重复请求需维持最终状态一致。

​示例​​:
用户支付时因网络延迟重复调用支付接口,若未做幂等,可能生成两笔扣款记录。


2. ​​资源分配与扣减​

  • ​库存扣减​​:秒杀场景中,多次请求需确保库存不被超卖。
  • ​优惠券/积分发放​​:用户领取优惠券或积分时,需防止重复领取。
  • ​账号注册​​:同一手机号或邮箱多次注册,需返回已存在的结果。

​示例​​:
库存扣减时,若重复扣减未校验幂等性,可能导致库存变为负数。


3. ​​数据更新与状态流转​

  • ​状态机操作​​:如工单从“处理中”变更为“已完成”,需确保状态仅变更一次。
  • ​字段更新​​:如用户余额增减(充值、提现),需避免重复累加或扣减。
  • ​配置修改​​:系统参数调整多次提交,需保证最终值与最后一次提交一致。

​示例​​:
用户提现时接口超时重试,若未做幂等,可能多次扣减余额。


4. ​​消息队列消费场景​

  • ​消息重复消费​​:MQ因ACK失败重发消息时,需保证业务逻辑仅执行一次。
  • ​异步任务处理​​:如批量导入数据,需确保任务ID唯一,避免重复导入。

​示例​​:
订单支付成功后发送MQ通知物流系统,若消息重复消费,需避免重复创建物流单。


为了保持接口的幂等性,一般的解决方案有以下

1. ​​Token 机制(一次性令牌)​

  • ​原理​​:客户端在发起请求前先获取一个唯一Token(如UUID),服务端存储该Token(如Redis)。接口处理时校验Token是否存在,存在则执行业务并删除Token,确保仅一次有效。

2. ​​唯一索引/数据库约束​

  • ​原理​​:利用数据库的唯一索引(如订单号、业务流水号),插入重复数据时触发唯一键冲突,拦截重复请求。 
CREATE TABLE orders (id BIGINT PRIMARY KEY,order_no VARCHAR(32) UNIQUE, -- 唯一约束...
);try {orderDao.insert(order);
} catch (DuplicateKeyException e) {// 捕获重复异常,返回幂等结果
}

3. ​​状态机校验​

  • ​原理​​:业务数据具有明确状态流转(如订单从“待支付”到“已支付”),接口处理前校验状态是否允许变更。
Order order = orderDao.findById(orderId);
if (!order.getStatus().equals(Status.PENDING)) {throw new IllegalStateException("状态已更新,拒绝操作");
}

4. ​​乐观锁(版本号/时间戳)​

  • ​原理​​:在数据更新时,通过版本号或时间戳实现乐观锁,确保只有匹配当前版本的请求生效 
UPDATE table SET value = 'new', version = version + 1 
WHERE id = #{id} AND version = #{currentVersion};int rows = jdbcTemplate.update(sql, params);
if (rows == 0) {throw new OptimisticLockException("数据已被修改");
}

5. ​​分布式锁控制​

  • ​原理​​:使用分布式锁(如Redis或ZooKeeper)保证同一业务ID的请求串行处理。
String lockKey = "order_lock_" + orderId;
Boolean locked = redisTemplate.opsForValue().setIfAbsent(lockKey, "1", 10, TimeUnit.SECONDS);
if (!locked) {throw new BusyException("请勿重复提交");
}
try {// 处理业务
} finally {redisTemplate.delete(lockKey);
}

6. ​​请求去重表​

  • ​原理​​:单独维护一张去重表,记录请求的唯一标识(如业务ID + 场景),处理前先查询是否已存在。
CREATE TABLE idempotent_record (id VARCHAR(64) PRIMARY KEY, -- 业务ID + 类型created_time TIMESTAMP
);String recordId = bizId + "_" + type;
if (idempotentDao.exists(recordId)) {return; // 直接返回历史结果
}
idempotentDao.insert(recordId);

 7. ​​限流与重试策略​

  • ​辅助方案​​:通过限流(如令牌桶)降低重复请求频率,结合客户端退避重试(Exponential Backoff)减少无效调用。
  • ​工具​​:使用Guava RateLimiter或Sentinel实现限流。

由于调用方目前无法配合预请求token的动作,我这次采用的是第五种方式,采用SpringAop+redis+注解的方式来做接口限制。

注解

import java.lang.annotation.*;/***  在需要保证接口幂等性的Controller的方法上使用此注解*  重复提交校验注解*/
@Target({ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ReSubmitCheck {//校验几秒内重复提交int seconds()  default 2;
}

核心逻辑,主要是通过注解+aop 的形式,在请求该接口前,先做判断,利用redis的原子操作,如果key在redis中存在,则说明在指定时间内,已经请求过了。

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;import javax.servlet.http.HttpServletRequest;
import java.util.concurrent.TimeUnit;@Aspect
@Component
@Slf4j
public class PreventReSummitAspect {/*** redis工具类*/@Autowiredprivate RedisTemplate<String, Object> redisTemplate;@Before("@annotation(reSubmitCheck)")public void preventReSubmit(JoinPoint joinPoint, ReSubmitCheck reSubmitCheck) {ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();//获取用户登录的accesstokenHttpServletRequest request = attributes.getRequest();String studentId = request.getParameter("studentId");if (studentId == null) {throw new RuntimeException("学生ID不能为空");}String senderType = StringUtils.isBlank(request.getParameter("senderType"))?"1":request.getParameter("senderType");String lockKey = "ReSubmit:" + studentId + "_" +senderType+"_"+request.getServletPath();Boolean result = redisTemplate.opsForValue().setIfAbsent(lockKey, lockKey, reSubmitCheck.seconds(), TimeUnit.SECONDS);if (!result) {System.out.println("重复请求:"+lockKey);throw new RuntimeException("重复请求:"+lockKey);}}}

使用

    @PostMapping(value = "/sendMsg")@ReSubmitCheck(seconds=2)public Result<String> sendMsg() throws IOException {}

postman测试

第一次请求



 紧接着第二次请求

 

http://www.dtcms.com/wzjs/462047.html

相关文章:

  • pos机网站建设方案b2b电子商务平台有哪些
  • 大连百度关键词优化合肥百度关键词优化
  • 免费建设网站制作免费外链代发平台
  • wordpress图片像素石家庄百度快速排名优化
  • 比亚迪新型实体企业充电宝关键词优化
  • pjblog wordpress优化设计答案五年级下册
  • 广州 网站备案刚刚北京传来重大消息
  • 网站建设技术的发展百度公司的业务范围
  • 南山网站建设百度做网站需要多少钱
  • python爬数据做网站无代码免费web开发平台
  • foxpay wordpressseo优化工具有哪些
  • 网络营销做私活网站百度手机助手网页版
  • 个人主页推荐武汉seo外包平台
  • 17网站一起做网店怎么样宁波网站建设公司
  • 泰安专业网站开发公司厦门网站seo
  • 雄安做网站学电脑办公软件培训班
  • 西安免费自助建站模板中国十大互联网公司
  • 政府网站建设经费预算方案百度搜索平台
  • 域名过期网站还有用吗长春网站排名提升
  • 搜狐快站生成app成人用品网店进货渠道
  • 做网站现在好弄么竞价托管 微竞价
  • 找生意做去哪个网站百度关键词搜索量统计
  • 政府网站建设方案.doc帮我搜一下长沙做网络销售
  • 上海做网站设计公司google推广 的效果
  • 洛阳网站推广怎么做seo推广软件品牌
  • 长沙专业网站制作郑州做网站推广电话
  • 做招聘网站怎么赚钱网站主题
  • 营销型网站建设团队2022年五月份热点事件
  • 河北响应式网站建设哪家有sem优化师是做什么的
  • 计算机毕设网站开发中期报告泉州seo代理计费