怎么解决java并发请求下数据插入重复问题
发表于:2026-11-01 作者:千家信息网编辑
千家信息网最后更新 2026年11月01日,本篇内容介绍了"怎么解决java并发请求下数据插入重复问题"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所
千家信息网最后更新 2026年11月01日怎么解决java并发请求下数据插入重复问题
本篇内容介绍了"怎么解决java并发请求下数据插入重复问题"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!
前言
前段时间发现数据库里经常会存在两条相同的用户数据,导致数据查询异常。查了原因,发现前端微信小程序在授权登录时,有时会出现同时发送了两条一模一样的请求(也就是常说的并发)。虽然后端代码有做防重复的判断,但是避免不了并发时候的重复性操作。于是就开始考虑并发的解决方案,解决方案有很多,从拦截请求到数据库层面都可以入手。
我们采用了对请求报文生成摘要信息+Redis分布式锁的方案。运行了一段时间,功能很可靠,代码也很简洁。于是上来做下记录以便后续参考。
解决方案说明:
系统架构用的Spring boot,定义一个Filter过滤器对请求进行过滤,然后对请求报文生成摘要信息并设置Redis分布式锁。通过摘要和锁判断是否为同一请求。
分布式锁工具类
public class ContextLJ { private static final Integer JD = 0; /** * 上锁 使用redis 为分布式项目 加锁 * @param sign * @param tiD * @return * @throws Exception */ public static boolean lock(String sign, String tiD) { synchronized (JD) { // 加锁 Cache cache = CacheManager.getCommonCache(sign); if(cache == null || StringUtils.isBlank(cache.getValue())) { CacheManager.putCommonCacheInfo(sign, tiD, 10000); return true; } return false; } } /** * 锁验证 * @param sign * @param tiD * @return */ public static boolean checklock(String sign, String tiD){ Cache cache = CacheManager.getCommonCache(sign); String uTid = StringUtils.replace(cache.getValue(), "\"", ""); return tiD.equals(uTid); } /** * 去掉锁 * @param sign * @param tiD */ public static void clent (String sign, String tiD){ if (checklock(sign, tiD)) { CacheManager.clearOnly(sign); } } /** * 获取摘要 * @param request */ public static String getSign(ServletRequest request){ // 此工具是将 request中的请求内容 拼装成 key=value&key=value2 的形式 源码在线面 String sign = null; try { Map map = getRequstMap((HttpServletRequest) request); // 生成摘要 sign = buildRequest(map); } catch (Exception e) { e.printStackTrace(); } return sign; } public static Map getRequstMap(HttpServletRequest req) throws Exception{ Map params = new HashMap(); params.put("uri", req.getRequestURI()); Map requestParams = req.getParameterMap(); for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext();) { String name = (String) iter.next(); String[] values = (String[]) requestParams.get(name); String valueStr = ""; for (int i = 0; i < values.length; i++) { valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ","; } params.put(name, valueStr); } return params; } private static String buildRequest(Map map) { List signList = new ArrayList<>(); for(Entry entry : map.entrySet()) { signList.add(entry.getKey() + "=" + entry.getValue()); } String sign = StringUtils.join(signList, "&"); return DigestUtils.md5Hex(sign); } } 在过滤器实现请求拦截
/** * 过滤频繁请求 */@Slf4j@Componentpublic class MyFilter implements Filter{ @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest request, ServletResponse myResp, FilterChain chain) throws IOException, ServletException { HttpServletRequest req = (HttpServletRequest) request; Boolean isDict = StringUtils.contains(req.getRequestURI(), "/dict/getDatas"); Boolean isFile = StringUtils.contains(req.getRequestURI(), "/files/file"); if(isDict || isFile) { chain.doFilter(request, myResp); // 查询数据字典或者文件,直接放行 return; } String sign = "sign_" + ContextLJ.getSign(request); // 生成摘要 String tiD = RandomUtils.randomCode(3) + "_" + Thread.currentThread().getId(); // 当前线程的身份 try { if (!ContextLJ.lock(sign, tiD)) { Map map = ContextLJ.getRequstMap((HttpServletRequest)request); log.warn("放弃相同并发请求【" + sign+ "】【" + tiD+"】"+JSON.toJSONString(map)); frequentlyError(myResp); return; } if (!ContextLJ.checklock(sign, tiD)) { Map map = ContextLJ.getRequstMap((HttpServletRequest)request); log.warn("加锁验证失败 【" + sign+ "】【" + tiD+"】"+JSON.toJSONString(map)); frequentlyError(myResp); return; } chain.doFilter(request, myResp); // 放行 } catch (Exception e) { // 捕获到异常 进行异常过滤 log.error("", e); myResp.getWriter().write(JSON.toJSONString(ApiRs.asError("服务器繁忙,请重试"))); } finally { ContextLJ.clent(sign, tiD); } } @Override public void destroy() { } /** * 频繁请求 */ private void frequentlyError(ServletResponse myResp) throws IOException { ((HttpServletResponse) myResp).setHeader("Content-type", "text/html;charset=UTF-8"); myResp.getWriter().write(JSON.toJSONString(ApiRs.asError("稍安勿躁,不要频繁请求"))); }} "怎么解决java并发请求下数据插入重复问题"的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注网站,小编将为大家输出更多高质量的实用文章!
数据
摘要
分布式
方案
生成
频繁
内容
解决方案
问题
相同
代码
信息
工具
报文
数据库
时间
更多
知识
过滤器
查询
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
互联网金融科技
互联网是第几次科技革命的成果
科技互联网企业
圆梦互联网科技
亿策互联网科技
致聘互联网科技
广州善班互联网科技
深圳艾佳互联网科技
佩信高科技互联网
太原新华互联网科技学校怎么样
博兴的互联网电子科技公司
玖二柒互联网科技公司待遇
哈尔滨新华互联网科技学院
欧洲十大科技互联网公司
美国互联网科技实力
张召忠谈中国互联网科技
互联网科技手抄报图片
互联网领先科技活动
深圳互联网科技园地址
中国主要互联网科技公司
狮子座互联网科技有限公司
善班互联网科技有限公司
壕鑫互联网络科技
互联网科技的未来发展
全球顶尖互联网科技公司
互联网媒体平台算高科技产业
哈尔滨屹滨互联网科技有限公司
张召忠谈中国互联网科技
广西科技产业互联网是什么
网互联网络科技