当前位置:科学 > 正文

RabbitMq如何实现-流量削峰?(一)

2023-03-05 17:50:20  来源:后端从入门到精通

搭建环境:springBoot + maven + RabbitMQ 3.8.14 + Erlang 23.2.7



(资料图片)

注意:安装时rabbitMq和erlang版本号必须对应,以免引起不必要的bug。


1、应用场景


应用解耦:当要调用远程系统时候,当存在订单系统和库存系统时,订单系统下单,库存系统需要收到订单后库存减一,这时候如果系统宕机,会造成订单丢失,吧订单消息发入mq,库存系统再去mq消费,就能解决这一问题。异步消费:传统的模式:用户下单—>邮件发送—>短信提醒,三个步骤全部完成,才能返回用户消费成功,因为后面两个步骤完全没有必须是当前时间完成,可以用户下单成功后,直接发送给mq,返回给用户消费成功,之后邮件发送和短信提醒,可以其他时间段来消费发送给用户。流量削峰:大型双11活动时候,0点有上亿并发,这时候数据库并不能承载那么大的数据冲击,而专门为高并发设计的mq可以承受住海量的请求,发送给mq,存储成功后,再消费。


2、流量削峰


本文主要介绍流量削峰实例,先创建两个表get_redpack和send_redpack。


CREATE TABLE send_redpack( id int not null AUTO_INCREMENT,     user_id varchar(32) not null comment "发红包用户",     money decimal(10,2) not null comment "红包金额",     unit_money decimal(10,2) not null comment "单个红包金额",     total int not null comment "红包个数",     remain int not null comment "红包剩余个数",     send_date datetime not null comment "发红包时间",     primary key(id));INSERT INTO send_redpack(user_id,money, unit_money,total,remain,send_date)VALUES("001",10000.00,10.00,1000,1000,now());CREATE TABLE get_redpack(id int not null AUTO_INCREMENT,user_id varchar(32) not null comment "抢红包用户",send_redpack_id int not null comment "发红包记录id",money decimal(10,2) not null comment "抢的红包金额",get_date datetime not null comment "抢红包时间",primary key(id));



本人用的是mac电脑brew安装的rabbitMq,启动rabbitMq用brew services strat rabbitmq,启动之后访问: http://localhost:15672/


登入的账号密码用guest,登入后可以在admin里面添加一个admin管理员,配置权限,在queues里面创建一个队列redpack,​供项目发用户ID到队列中。


​编辑

​编辑上面的流程处理完之后,就可以在springboot项目中引入rabbitMq包,配置文件,及其新建上面表的实体类。


<!--rabbitmq-->        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-amqp</artifactId>        </dependency># ----- RabbitMq -------- #spring.rabbitmq.virtual-host=/spring.rabbitmq.host=localhostspring.rabbitmq.port=5672spring.rabbitmq.username=adminspring.rabbitmq.password=admin



/** * 抢红包 * * @author keying * @date 2021/6/22 */@Datapublic class GetRedpack {    /**     *     */    private Integer id;    /**     * 抢红包用户     */    private String userId;    /**     * 发红包用户     */    private String sendRedpackId;    /**     * 抢的红包金额     */    private BigDecimal money;    /**     * 抢红包时间     */    private Date getDate;}



/** * 发红包 * @author keying * @date 2021/6/22 */@Datapublic class SendRedpack {    /**     *     */    private Integer id;    /**     * 发红包用户     */    private String userId;    /**     * 红包金额     */    private BigDecimal money;    /**     * 单个红包金额     */    private BigDecimal unitMoney;    /**     * 红包个数     */    private Integer total;    /**     * 红包剩余个数     */    private Integer remain;    /**     * 发红包时间     */    private Date sendDate;}



下面先写provider生产者的代码,进入接口发送红包,发送100个,然后把收红包的用户id发给mq:


/** * 生产者 * * @author keying * @date 2021/6/22 */@RestController@Slf4j@RequestMapping("/provider")public class ProviderController {    @Resource    private RabbitMqService rabbitMqService;    @RequestMapping("/send_redpack")    public void sendRedpack(){        for (int i = 0; i < 100; i++) {            rabbitMqService.sendRedpack(i);        }    }}@Resource    private RabbitTemplate rabbitTemplate;    @Override    public void sendRedpack(int i) {        rabbitTemplate.convertAndSend("redpack", i);    }



然后写消费者代码,用@rabbitListener监听queue,队列就是刚刚在mq管路页面创建的redpack,定义的发红包用户为001,为了方便测试,在代码里写死,给消费者的类加一个@Component的注解,交给spring容器管理,消费逻辑大致就是:


1、先查看红包剩余数,大于0则继续,否则结束。


2、吧红包剩余数-1.


3、抢红包信息存入get_redpack表,存储抢红包详情。


/** * 消费 * * @author keying * @date 2021/6/22 */@Component@Slf4jpublic class ConsumerRabbitMq {    @Resource    private RabbitMqMapper rabbitMqMapper;    private static final String sendUserId = "001";    /**     * 需在RabbitMQ中手动创建redpack 队列,否则报错     * @param message     */    @RabbitListener(queues = "redpack")    public void getRedpack(String message){        log.info("接收的消费红包人员: {}", message);        try {            //查询红包剩余个数是否大于0            int remain = rabbitMqMapper.getRemain(sendUserId);            if(remain > 0) {                //扣减红包个数                int result = rabbitMqMapper.deleteOne(sendUserId);                if(result > 0) {                    //3.新增用户抢红包记录                    GetRedpack getRedpack = new GetRedpack();                    getRedpack.setUserId(message);                    getRedpack.setSendRedpackId(sendUserId);                    getRedpack.setGetDate(new Date());                    getRedpack.setMoney(new BigDecimal("10"));                    rabbitMqMapper.insertGetRedpack(getRedpack);                }            }            //异步通知用户抢红包成功        } catch (Exception e) {            log.error("处理抢单异常:" + e.getMessage());            throw new RuntimeException("处理抢单异常");        }    }}



附上三个sql。。。


<select id="getRemain" parameterType="java.lang.String" resultType="java.lang.Integer">        select remain from send_redpack where user_id = #{sendUserId}    </select>    <delete id="deleteOne" parameterType="java.lang.String">        update send_redpack set remain = remain-1 where user_id = #{sendUserId}    </delete>    <insert id="insertGetRedpack" parameterType="com.alibaba.first.model.GetRedpack">        insert into get_redpack (user_id,send_redpack_id,money,get_date)        values (#{userId},#{sendRedpackId},#{money},#{getDate})    </insert>



重点、重点、重点、注意点事项(重要的事要说三遍),踩坑总结:


1、安装时候,rabbitMq和erlang版本号对应一致。


2、springboot集成rabbitMq,guest只能登入localoal,远程ip,需要创建admin用户,用admin用户登入。


最后,看到这里的读者,喜欢的话安排一波(点赞,收藏,关注),原创不易,每周定期分享编程笔记。

关键词: 美好,一直在身边 Erlang 关晓彤江疏影 Mac电脑 2019科技之光

推荐阅读

通用设备介绍 通用设备包括什么?

通用设备介绍一、通用设备。办公和商务通用设备,包括文化办公机械、消防设备、电机、变压器、锅炉、空调设备、清洁卫生设备、通讯设备、视 【详细】

美国UFO探索事件 全面解析美国UFO探索事件

一般在发生UFO探索事件之后,许多的研究人员都会认真的去分析此事件发生的前因后果,去搜集一些相关的证据,但是其实我们还能够从这些事件 【详细】

汽车吸尘器好用吗?汽车吸尘器真的有用么?

现在随着大家都逐渐拥有了自己的汽车,很多人对汽车的一些相关工具也还是逐步的关注了起来。其中车载吸尘器就是大家关注度最高的产品,那么 【详细】

航天员太空生活舱内景曝光 在太空中航天员之间是如何交流的呢?

航天员太空生活舱内景曝光,航天员在天上是如何生活的呢?中国载人航天工程空间站、神舟系列载人飞船、天舟系列货运飞船和长征系列运载火箭 【详细】

稀土镁合金简介 稀土镁合金的未来发展趋势

稀土镁合金一般指稀土元素的镁合金。镁合金是工程应用中最轻的金属结构材料,具有低密度、高比强度、高比刚度、高减震、易加工、易回收等优 【详细】

关于我们  |  联系方式  |  免责条款  |  招聘信息  |  广告服务  |  帮助中心

联系我们:85 572 98@qq.com备案号:粤ICP备18023326号-40

科技资讯网 版权所有