当前位置:首页 > 房产信息

淘宝购物车代码 淘宝购物车是如何使用Spring Boot+Redis 扛住十万qps重复提交的(含代码实例)

前言:

在实际的开发项目中,一个暴露于外部世界的接口经常会面临大量即时提交的重复请求。要想过滤掉重复请求对业务造成的危害,就需要实现幂等性!

让我们解释幂等性的概念:

任何多次执行的影响与一次执行的影响相同。按照这个意思,最后的意思就是对数据库的影响只能是一次性的,不能重复处理。

如何保证其幂等性,通常有以下几种手段:

1.数据库建立一个唯一的索引,这可以确保最终只有一条数据被插入到数据库中。2.令牌机制在每个接口请求之前获得一个令牌,然后在下一个请求中将这个令牌添加到请求的头体中,并在后台验证它。如果验证通过,删除令牌,然后在下一个请求中再次判断令牌3、悲观锁还是乐观锁。悲观锁可以保证其他sql每次更新都不能更新数据(当数据库引擎为innodb时,select的条件必须是唯一的索引,以防止锁定整个表)。4.先质疑再判断。首先,查询数据库中是否有数据。如果存在,则证明已经被请求,直接拒绝请求。如果不存在,证明是第一次进来直接放出来。

redis实现自动幂等的示意图;

Spring Boot+Redis坚持住,瞬间提交上千次(例子)

首先,构建redis的服务Api

1.首先,建立redis服务器。

2.在Spring封装的springboot或jedis中引入redis的stater是可以的。后来主要使用的api是它的set方法和exists方法。这里我们使用封装的回弹模板。

/** * redis工具类 */ @Componentpublic classRedisService{

@ autowiredprivateredestemplate redis template;

/* * *写缓存* @ param key * @ param value * @ return */public boolean set(final string key,object value){ boolean result = false;

尝试{ ValueOperations & lt可序列化,对象>;operations = redistemplate . opsforvalue;运营。set(键、值);result = true} catch(Exception e){ e . printstacktrace;} returnresult}

/* * *写缓存集老化时间* @ param key * @ param value * @ return */public boolean setex(final string key,object value,long expire time){ boolean result = false;

尝试{ ValueOperations & lt可序列化,对象>;operations = redistemplate . opsforvalue;运营。set(键、值);redisTemplate.expire(key,expireTime,TimeUnit。秒);result = true} catch(Exception e){ e . printstacktrace;} returnresult}

/* * *判断缓存中是否存在对应的值* @ param key * @ return */public boolean exists(final string key){ returnredistemplate . haskey(key);}

/* * *

public Object get(FinaliString键){ Object result = nullValueOperations<。可序列化,对象>;operations = redistemplate . opsforvalue;结果=操作。get(key);returnresult}

/* * *删除相应的值* @ param key */public boolean remove(final string key){ if(exists(key)){ boolean delete = redis template . delete(key);returndelete} returnfalse}}

第二,自定义注释自动增强

自定义注释。定义这个注释的主要目的是将其添加到需要实现幂等性的方法中。任何方法注释它都会实现自动幂等。后台用反射。如果扫描这个标注,就会对这个方法进行处理,实现自动幂等。元注释元素类型。方法表示只能放在方法上,而扩展策略。RUNTIME表示它正在运行。

@ Target({ ElementType.METHOD}) @ Retention( RetentionPolicy. RUNTIME) public @interface AutoIdempotent {

}

三.令牌创建和检查

1.令牌服务接口

我们创建了一个新的接口和一个令牌服务。主要有两种方法,一种用于创建令牌,另一种用于验证令牌。创建令牌主要产生一个字符串。检查令牌时,主要传递请求对象。为什么要传递请求对象?主要功能是获取头中的令牌,然后进行检查,通过抛出的Exception获取具体的错误信息,返回给前端。

publicinterfaceTokenService{ /*** 创建token * @return*/publicString createToken;

/* * *验证令牌* @ param request * @ return */public boolenchecktoken(http servlet请求请求)引发异常;

}

2.令牌的服务实现类

Token指redis服务。创建令牌并使用random算法工具类生成random uuid字符串,然后放入redis(为了防止冗余数据保留,到期时间设置为10000秒,具体取决于业务)。如果令牌成功放入,令牌值将最终返回。checkToken的方法是从header获取Token到value(如果header中没有,从paramter获取),如果不存在,直接抛出异常。这种异常信息可以被拦截器捕获,然后返回到前端。

@ServicepublicclassTokenServiceImplimplementsTokenService{

@ autowiredprivateredeservice redis service;

/* * *

@ OverridePublicString create token { String str = randomutil . randomuuid;StrBuilder token = newStrBuilder

尝试{ token.append(常量。Redis.TOKEN_PREFIX)。append(str);redis service . setex(token.toString,token . tostring,10000 l);booleannotEmpty = strutil . isnotempty(token . tostring);

if(notEmpty){ return token . ToString;} } catch(Exception ex){ ex . printstacktrace;} returnnull}

/* * *检查令牌* * @ param request * @ return */@ override public boolenchecktoken(http servlet请求请求)引发异常{

字符串标记= request.getHeader(常量。TOKEN _ NAME);token token = request . getparameter(constant . token _ name)在if(struil . is blank(token)){//header中不存在;if(strutil . is blank(token)){//参数中也没有token row newserviceexception(constant . response code . invalid _ argument,100);}}

if(!redis service . exists(token)){ throwNewServiceException(常量)。response code . REPLICATIONAL _ OPERATION,200);}

booleandremove = rediservice . remove(token);if(!移除){ thrownewServiceException(常量。response code . REPLICATIONAL _ OPERATION,200);}

returntrue}}

四.拦截器的配置

1.实现WebMvcConfigurerAdapter的web配置类,主要是用来给配置类添加autoIdempotentInterceptor,这样只有到了拦截器的时候才能生效。请注意使用@Configuration注释,以便在容器启动时可以将其添加到上下文中。

@ConfigurationpublicclassWebConfigurationextendsWebMvcConfigurerAdapter{

@ ResourcePrivateAutoDemmendeinterceptor AutoDemmendeinterceptor;

/* * *添加拦截器* @ param registry */@ override public viddinterceptors(拦截器注册表){注册表。addinterceptor(自动拦截器);super.addInterceptors(注册表);}}

2.拦截处理器:主要功能是拦截并扫描AutoIdempotent to annotation to方法,然后调用TokenService的checkToken方法验证token是否正确,如果捕获到异常,则将异常信息渲染为json返回给前端

/*** 拦截器*/@ComponentpublicclassAutoIdempotentInterceptorimplementsHandlerInterceptor{

@ AutowiredprivateTokenService令牌服务;

/* * *预处理* * @ param request * @ param response * @ param handler * @ return * @ throwsException */@ overrideepublibooreanphandle(http servlet request,HttpServletResponse response,Object handler)throwsException { if(!(处理程序实例方法(){ returntrue}

handler method handler method =(handler method)处理程序;method method = HandlerMethod . GetMethod;//扫描由ApiIdempotment auto幂等方法批注= method.getannotation (auto幂等. class)标记;

if(methodAnnotation!= null){ try { returntokenservice . check token(请求);//幂等验证,通过则释放,失败则抛出异常,通过统一异常处理返回友好提示} catch(exception ex ){

ResultVo failed result = ResultVo . getfailed result(101,ex . getmessage);writeReturnJson(response,jsonutil . tojsonstr(failedResult));throwex} }//必须返回true,否则所有请求都会被拦截

returntrue}

@ OverridePublicavityPostHandle(HttpServletrequest请求,HttpServletResponse响应,对象处理程序,模型和视图模型和视图)抛出异常{

}

@ override publicationaftercompletion(HttpServletrequest请求,HttpServletResponse响应,对象处理程序,异常ex)throwsException {

}

/* * *返回json值* @ param response * @ param JSON * @ throwsexception */private voitwriterreturnjson(http servlet response,string JSON)throwsexception { print writer = null;response . setcharacterencoding(" UTF-8 ");response . SetContentType(" text/html;charset = utf-8 ");

请尝试{ writer = response.getWriterwriter . print(JSON);} catch(IOException e) {

}最后{ if(writer!= null)writer . close;}}}

动词 (verb的缩写)测试案例

1.模拟业务请求类

首先我们需要通过/get/token路径通过getToken方法获取具体的令牌,然后我们调用testIdempotence方法,用@ AutoIdempotent注释。拦截器将拦截所有请求。当判断标注在处理方法上时,会调用TokenService中的checkToken方法。如果捕获到异常,该异常将被引发给调用方。让我们模拟下面的请求:

@RestControllerpublicclassBusinessController{ @ResourceprivateTokenService tokenService; @ResourceprivateTestService testService;

@ post mapping("/get/token ")public StrIng GetToken { StrIng token = TokenServiCe . CreateToken;if(Strutil . is notempty(token)){ ResultVo ResultVo = new ResultVo;resultVo.setCode(常量. code _ success);结果设置消息(常量。SUCCESS);resultVo.setData(令牌);returnjsonutil . tojsonstr(resultVo);}

returnStrUtil。EMPTY}

@ AutoIdemPoint @ post mapping("/test/幂等")publicString TestidemPointS { String business result = TestServiCe . TestidemPointS;if(StratIl . is notempty(business result)){ ResultVo successResult = ResultVo . getsuccessresult(business result);returnjsonutil . tojsonstr(successResult);}

returnStrUtil。EMPTY}}

2.使用邮递员请求

首先,访问get/token路径以获取特定的令牌:

Spring Boot+Redis坚持住,瞬间提交上千次(例子)

通过使用获得的令牌并将其放入特定的请求头,我们可以看到第一个请求成功了,然后我们请求了第二次:

Spring Boot+Redis坚持住,瞬间提交上千次(例子)

对于第二个请求,是重复操作,说明重复验证已经通过。当我们多次要求时,只会让它第一次成功,第二次失败:

Spring Boot+Redis坚持住,瞬间提交上千次(例子)

不及物动词总结

本博客介绍了如何使用springboot、interceptor和redis优雅地实现接口的幂等性,这在实际开发过程中非常重要,因为一个接口可能会被无数的客户端调用。如何保证不影响后台的业务处理,如何保证只影响数据一次,非常重要。可以防止产生脏数据或者混乱数据,还可以降低并发性,这是一件非常有益的事情。但是传统的方法是每次判断数据,不够智能和自动化,比较麻烦。今天的自动化处理也可以提高程序的可扩展性。

来源:https://www.jianshu.com/p/9aef0c40b1b9

1.《淘宝购物车代码 淘宝购物车是如何使用Spring Boot+Redis 扛住十万qps重复提交的(含代码实例)》援引自互联网,旨在传递更多网络信息知识,仅代表作者本人观点,与本网站无关,侵删请联系页脚下方联系方式。

2.《淘宝购物车代码 淘宝购物车是如何使用Spring Boot+Redis 扛住十万qps重复提交的(含代码实例)》仅供读者参考,本网站未对该内容进行证实,对其原创性、真实性、完整性、及时性不作任何保证。

3.文章转载时请保留本站内容来源地址,https://www.lu-xu.com/fangchan/1612083.html

上一篇

京剧十大名曲 全套中国10大名曲,完整合辑,美到心窝

下一篇

如何判断自己身上有仙 怎么看到自己的仙家?身上带仙看哪个手指

热重分析仪 热重分析仪的常见故障和解决方法

热重分析仪 热重分析仪的常见故障和解决方法

热重分析仪是一种利用热重分析来检测物质温度与质量关系的仪器。热重法是在程序升温控制下,测量物质质量与温度(或时间)的关系。当被测物质在加热过程中升华、汽化、分解成气体或失去结晶水时,被测物质的质量会发生变化。此时,热重曲线不是直线而是下降。通过分析热重曲线,可以知道被测物质变化到什么程度,...

魔兽战网 「魔兽世界」战网剩余点数兑换方法

  • 魔兽战网 「魔兽世界」战网剩余点数兑换方法
  • 魔兽战网 「魔兽世界」战网剩余点数兑换方法
  • 魔兽战网 「魔兽世界」战网剩余点数兑换方法

吸管折星星 实践动手| 塑料吸管折星星的方法

  • 吸管折星星 实践动手|  塑料吸管折星星的方法
  • 吸管折星星 实践动手|  塑料吸管折星星的方法
  • 吸管折星星 实践动手|  塑料吸管折星星的方法

折星星的方法 实践动手| 塑料吸管折星星的方法

  • 折星星的方法 实践动手|  塑料吸管折星星的方法
  • 折星星的方法 实践动手|  塑料吸管折星星的方法
  • 折星星的方法 实践动手|  塑料吸管折星星的方法

吸管星星 实践动手| 塑料吸管折星星的方法

  • 吸管星星 实践动手|  塑料吸管折星星的方法
  • 吸管星星 实践动手|  塑料吸管折星星的方法
  • 吸管星星 实践动手|  塑料吸管折星星的方法

管道温度传感器 温度传感器的安装方法

  • 管道温度传感器 温度传感器的安装方法
  • 管道温度传感器 温度传感器的安装方法
  • 管道温度传感器 温度传感器的安装方法

水管温度传感器 温度传感器的安装方法

  • 水管温度传感器 温度传感器的安装方法
  • 水管温度传感器 温度传感器的安装方法
  • 水管温度传感器 温度传感器的安装方法

巫术使用方法大全 普通人能用的茅山道术有哪些?茅山道术驱鬼口诀手法揭秘

  • 巫术使用方法大全 普通人能用的茅山道术有哪些?茅山道术驱鬼口诀手法揭秘
  • 巫术使用方法大全 普通人能用的茅山道术有哪些?茅山道术驱鬼口诀手法揭秘
  • 巫术使用方法大全 普通人能用的茅山道术有哪些?茅山道术驱鬼口诀手法揭秘