RabbitMq如何实现流量削峰?(一)
搭建环境:springBootmavenRabbitMQ3。8。14Erlang23。2。7
注意:安装时rabbitMq和erlang版本号必须对应,以免引起不必要的bug。
1、应用场景
应用解耦:当要调用远程系统时候,当存在订单系统和库存系统时,订单系统下单,库存系统需要收到订单后库存减一,这时候如果系统宕机,会造成订单丢失,吧订单消息发入mq,库存系统再去mq消费,就能解决这一问题。异步消费:传统的模式:用户下单邮件发送短信提醒,三个步骤全部完成,才能返回用户消费成功,因为后面两个步骤完全没有必须是当前时间完成,可以用户下单成功后,直接发送给mq,返回给用户消费成功,之后邮件发送和短信提醒,可以其他时间段来消费发送给用户。流量削峰:大型双11活动时候,0点有上亿并发,这时候数据库并不能承载那么大的数据冲击,而专门为高并发设计的mq可以承受住海量的请求,发送给mq,存储成功后,再消费。
2、流量削峰
本文主要介绍流量削峰实例,先创建两个表getredpack和sendredpack。
CREATETABLEsendredpack(idintnotnullAUTOINCREMENT,useridvarchar(32)notnullcomment发红包用户,moneydecimal(10,2)notnullcomment红包金额,unitmoneydecimal(10,2)notnullcomment单个红包金额,totalintnotnullcomment红包个数,remainintnotnullcomment红包剩余个数,senddatedatetimenotnullcomment发红包时间,primarykey(id));INSERTINTOsendredpack(userid,money,unitmoney,total,remain,senddate)VALUES(001,10000。00,10。00,1000,1000,now());CREATETABLEgetredpack(idintnotnullAUTOINCREMENT,useridvarchar(32)notnullcomment抢红包用户,sendredpackidintnotnullcomment发红包记录id,moneydecimal(10,2)notnullcomment抢的红包金额,getdatedatetimenotnullcomment抢红包时间,primarykey(id));
本人用的是mac电脑brew安装的rabbitMq,启动rabbitMq用brewservicesstratrabbitmq,启动之后访问:http:localhost:15672
登入的账号密码用guest,登入后可以在admin里面添加一个admin管理员,配置权限,在queues里面创建一个队列redpack,供项目发用户ID到队列中。
编辑
编辑上面的流程处理完之后,就可以在springboot项目中引入rabbitMq包,配置文件,及其新建上面表的实体类。
!rabbitmqdependencygroupIdorg。springframework。bootgroupIdspringbootstarteramqpartifactIddependencyRabbitMqspring。rabbitmq。virtualhostspring。rabbitmq。hostlocalhostspring。rabbitmq。port5672spring。rabbitmq。usernameadminspring。rabbitmq。passwordadmin
抢红包authorkeyingdate2021622DatapublicclassGetRedpack{privateIntegerid;抢红包用户privateStringuserId;发红包用户privateStringsendRedpackId;抢的红包金额privateBigDecimalmoney;抢红包时间privateDategetDate;}
发红包authorkeyingdate2021622DatapublicclassSendRedpack{privateIntegerid;发红包用户privateStringuserId;红包金额privateBigDecimalmoney;单个红包金额privateBigDecimalunitMoney;红包个数privateIntegertotal;红包剩余个数privateIntegerremain;发红包时间privateDatesendDate;}
下面先写provider生产者的代码,进入接口发送红包,发送100个,然后把收红包的用户id发给mq:
生产者authorkeyingdate2021622RestControllerSlf4jRequestMapping(provider)publicclassProviderController{ResourceprivateRabbitMqServicerabbitMqService;RequestMapping(sendredpack)publicvoidsendRedpack(){for(inti0;i100;i){rabbitMqService。sendRedpack(i);}}}ResourceprivateRabbitTemplaterabbitTemplate;OverridepublicvoidsendRedpack(inti){rabbitTemplate。convertAndSend(redpack,i);}
然后写消费者代码,用rabbitListener监听queue,队列就是刚刚在mq管路页面创建的redpack,定义的发红包用户为001,为了方便测试,在代码里写死,给消费者的类加一个Component的注解,交给spring容器管理,消费逻辑大致就是:
1、先查看红包剩余数,大于0则继续,否则结束。
2、吧红包剩余数1。
3、抢红包信息存入getredpack表,存储抢红包详情。
消费authorkeyingdate2021622ComponentSlf4jpublicclassConsumerRabbitMq{ResourceprivateRabbitMqMapperrabbitMqMapper;privatestaticfinalStringsendUserId001;需在RabbitMQ中手动创建redpack队列,否则报错parammessageRabbitListener(queuesredpack)publicvoidgetRedpack(Stringmessage){log。info(接收的消费红包人员:{},message);try{查询红包剩余个数是否大于0intremainrabbitMqMapper。getRemain(sendUserId);if(remain0){扣减红包个数intresultrabbitMqMapper。deleteOne(sendUserId);if(result0){3。新增用户抢红包记录GetRedpackgetRedpacknewGetRedpack();getRedpack。setUserId(message);getRedpack。setSendRedpackId(sendUserId);getRedpack。setGetDate(newDate());getRedpack。setMoney(newBigDecimal(10));rabbitMqMapper。insertGetRedpack(getRedpack);}}异步通知用户抢红包成功}catch(Exceptione){log。error(处理抢单异常:e。getMessage());thrownewRuntimeException(处理抢单异常);}}}
附上三个sql
selectidgetRemainparameterTypejava。lang。StringresultTypejava。lang。Integerselectremainfromsendredpackwhereuserid{sendUserId}selectdeleteiddeleteOneparameterTypejava。lang。Stringupdatesendredpacksetremainremain1whereuserid{sendUserId}deleteinsertidinsertGetRedpackparameterTypecom。alibaba。first。model。GetRedpackinsertintogetredpack(userid,sendredpackid,money,getdate)values({userId},{sendRedpackId},{money},{getDate})insert
重点、重点、重点、注意点事项(重要的事要说三遍),踩坑总结:
1、安装时候,rabbitMq和erlang版本号对应一致。
2、springboot集成rabbitMq,guest只能登入localoal,远程ip,需要创建admin用户,用admin用户登入。
最后,看到这里的读者,喜欢的话安排一波(点赞,收藏,关注),原创不易,每周定期分享编程笔记。