详解java解决分布式环境中高并发环境下数据插入重复问题

  

java解决分布式环境中高并发环境下数据插入重复问题

  

  

原因:服务器同时接受到的重复请求
  现象:数据重复插入/修改操作

  

解决方案:分布式锁

  

对请求报文生成摘要信息+复述,实现分布式锁

  

  

分布式锁的应用
  

        包com.nursling.web.filter.context;      进口com.nursling.nosql.redis.RedisUtil;   进口com.nursling.sign.SignType;   进口com.nursling.sign.SignUtil;   进口redis.clients.jedis.Jedis;      与javax . servlet . servletrequest进口;   进口javax.servlet.http.HttpServletRequest;   进口java.util.HashMap;   进口java.util.Map;/* *   *并发拦截   *高并发下过滤掉相同请求的工具   * @author杨。   *   */公开课ContextLJ {      私有静态最终整数JD=0;/* *   *上锁使用复述,为分布式项目加锁   * @param标志   * @param tiD   * @return   * @throws例外   */公共静态逻辑锁(String, String tiD) {   同步(JD){//加锁   能能=RedisUtil.getJedis ();   字符串uTid=jedis.get(信号);   如果(uTid==null) {   能。集(符号,tiD);   能。到期(符号,36);   返回true;   }   返回错误;   }   }/* *   *锁验证   * @param标志   * @param tiD   * @return   */公共静态布尔checklock (String, String tiD) {   能能=RedisUtil.getJedis ();   字符串uTid=jedis.get(信号);   返回tiD.equals (uTid);   }/* *   *去掉锁   * @param标志   * @param tiD   */公共静态孔隙clent(字符串,字符串tiD) {   如果(checklock(符号,tiD)) {   能能=RedisUtil.getJedis ();   jedis.del(信号);   }   }/* *   *获取摘要   * @param请求   * @return   */公共静态字符串getSign (ServletRequest请求){//此工具是将请求中的请求内容拼装成键=value&关键=value2的形式源码在线面   String> Map<字符串;地图=SignUtil.getRequstMap ((HttpServletRequest)请求);   弦信号=零;   尝试{//这里使用md5方法生成摘要SignUtil。getRequstMap方法源码就不贴了=SignUtil迹象。buildRequest(地图,SignType.MD5);   }捕捉(异常e) {   e.printStackTrace ();   }   返回信号;   }   }   之前            公共静态Map<字符串,String>getRequstMap (HttpServletRequest点播){   String> Map<字符串;params=new HashMap<字符串,String> ();   Mapiter=requestParams.keySet () .iterator ();iter.hasNext ();) {   字符串名称=(字符串)iter.next ();   String[]值=(String []) requestParams.get(名称);   字符串valueStr=" ";   for (int i=0;我& lt;values.length;我+ +){   valueStr=(i==值。长度- 1)& # 63;valueStr +值[我]   :valueStr[我]+”、“+值;   }   参数个数。把(名称、valueStr);   }   返回参数;   }   之前      

下面是过滤器代码

  

对分布式锁的利用

        包com.nursling.web.filter.transaction;      进口com.google.gson.Gson;   进口com.nursling.common.RandomUtil;   进口com.nursling.dao.util.TransactionUtils;   进口com.nursling.model.ApiResult;   进口com.nursling.model.ApiRtnCode;   进口com.nursling.web.filter.context.ContextLJ;   进口org.apache.log4j.Logger;      进口javax.servlet。*;   进口javax.servlet.http.HttpServletResponse;   进口java.io.IOException;/* *   *对事物进行控制并且避免接口直接报漏异常信息   *并且过滤频繁请求   *由yangchao 2016/11/4。   */公共类TransactionFilter实现滤波器{      日志记录器=Logger.getLogger (this.getClass ());      @Override   FilterConfig FilterConfig公共空init()抛出ServletException {   }      @Override   doFilter (ServletRequest公共无效请求,ServletResponse myResp, FilterChain链)抛出IOException, ServletException {   弦信号=" sign_ " + ContextLJ.getSign(请求);//生成摘要   字符串tiD=RandomUtil.getRandomString (3) +“_”+ Thread.currentThread () .getId ();//当前线程的身份   尝试{   如果(! ContextLJ。锁(标志,tiD)) {   日志。警告(“放弃相同并发请求“+签名);   frequentlyError (myResp);   返回;   }   如果(! ContextLJ。checklock(符号,tiD)) {   日志。警告(“加锁验证失败" + + " " + tiD迹象);   frequentlyError (myResp);   返回;   }   链。doFilter(请求,myResp);//放行   }捕捉(异常e){//捕获到异常进行异常过滤   日志。错误(“e);   retrunErrorInfo (myResp);   最后}{   ContextLJ。clent(符号,tiD);   }   }/* *   *频繁请求   * @param myResp   */私人空白frequentlyError (ServletResponse myResp)抛出IOException {   ApiResult

详解java解决分布式环境中高并发环境下数据插入重复问题