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解决分布式环境中高并发环境下数据插入重复问题