您的位置:首页 > 游戏 > 游戏 > 互联网平台排名_python自学必看的3本书_广告接单有什么平台_天津百度快照优化公司

互联网平台排名_python自学必看的3本书_广告接单有什么平台_天津百度快照优化公司

2024/9/22 19:18:46 来源:https://blog.csdn.net/weixin_64704029/article/details/142343214  浏览:    关键词:互联网平台排名_python自学必看的3本书_广告接单有什么平台_天津百度快照优化公司
互联网平台排名_python自学必看的3本书_广告接单有什么平台_天津百度快照优化公司

核心思路:

当用户发出提交请求时,在 Redis 中创建一个带有过期时间的唯一标识,表示这个请求已经提交过了。如果 Redis 中已经存在这个标识,则拒绝本次提交,避免重复操作。

基本准备:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><version>2.7.10</version>
</dependency>
<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.30</version>
</dependency>
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId><version>2.7.10</version>
</dependency>

大体思路:在业务侧进行加锁的幂等判断,在规定时间内操作只能算一次成功的请求

import com.sa.config.RedissonManager;
import org.redisson.api.RLock;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;@Service
public class RepeatedSubmitService {@Resourceprivate RedisTemplate redisTemplate;private static final long EXPIRE_TIME = 5;  // 过期时间,单位秒/*** 防止重复提交操作* @param userId userId 用户ID* @param actionId actionId 操作标识(可以是业务类型或者表单ID等)* @return true 表示操作允许,false 表示重复提交*/public boolean check(String userId,String actionId){// 生成redisKey,作为唯一标识String redisKey = "submitLock:"+userId+":"+actionId;// 尝试使用 SETNX 来防止重复提交,返回 true 表示设置成功(没有重复提交)Boolean success = redisTemplate.opsForValue().setIfAbsent(redisKey,"LOCKED",EXPIRE_TIME, TimeUnit.SECONDS);if (Boolean.TRUE.equals(success)){return true;}else{// Redis 中已经存在锁键,说明是重复提交return false;}}public void submit(String userId,String actionId){if (check(userId,actionId)){System.out.println("业务操作成功");}else {System.out.println("重复提交");}}}
package com.sa.controller;import com.sa.pojo.Order;
import com.sa.service.RepeatedSubmitService;
import lombok.extern.log4j.Log4j2;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;@Log4j2
@RestController
public class OrderController {@Resourceprivate RepeatedSubmitService repeatedSubmitService;@GetMapping("/submit")public void submit(@RequestBody Order order){String userId = order.getUserId();String actionId = order.getActionId();log.info("userId:{},actionId:{}",userId,actionId);repeatedSubmitService.submit(userId,actionId);}
}

在5秒内的重复提交记录,只能是一条生效,剩余的请求在业务侧进行失效处理

改进

此处还可以基于本地缓存实现,这里采用Map模拟,也可以使用Caffine本地缓存

import org.springframework.stereotype.Service;import java.util.HashMap;
import java.util.Map;/*** 幂等性校验*/
@Service
public class IdempotencyService {private Map<String, Boolean> requestCache = new HashMap<>();/*** 检查是否是重复的请求** @param requestId* @return*/private synchronized boolean check(String requestId) {if (requestCache.containsKey(requestId)) {return false;}requestCache.put(requestId, true);return true;}/*** 模拟业务操作*/public void processRequest(String requestId) {if (check(requestId)) {// 处理业务逻辑System.out.println("处理请求: " + requestId);} else {System.out.println("请求重复: " + requestId);}}}

或是使用Redisson来进行实现:

  • RLock 替代 setIfAbsent:Redisson 的 RLock 封装了 Redis 分布式锁的功能,简化了操作。通过 lock.tryLock 来尝试获取锁,获取成功则继续执行操作,获取失败则表示重复提交。

  • 自动续期和过期时间:Redisson 内置了看门狗机制,会自动续期锁,防止长时间业务执行时锁提前释放。通过 tryLock(100, EXPIRE_TIME, TimeUnit.SECONDS) 可以设置锁的最大等待时间和最大存活时间,超时后锁自动释放。

  • 锁的释放:Redisson 自动确保锁的释放在 finally 块中进行,避免因异常导致锁未被释放。

    public boolean checkForRedisson(String userId,String actionId){// 生成redisKey,作为唯一标识String redisKey = "submitLock:"+userId+":"+actionId;// 获取分布式锁对象RLock lock = RedissonManager.getClient().getLock(redisKey);try{Boolean success = lock.tryLock(100,EXPIRE_TIME, TimeUnit.SECONDS);if (success){return true;}else{return false;}}catch (InterruptedException e) {Thread.currentThread().interrupt();return false;}finally {if(lock.isHeldByCurrentThread()){lock.unlock();}}}

 

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com