day23 整合xxl-job上传近三天秒杀商品

news2024/12/25 10:24:01

整合xxl-job

1.部署调度中心

  • 将doc目录下的sql脚本导入数据库

    image-20221217170037353

  • 修改日志位置

    image-20221217205650076

  • maven打包mvn pageage -Dmaven.skip.test=true

  • 后台方式启动 nohup java -jar xxl-job-admin-2.3.0.jar > tag-web.log 2>&1 &

  • 访问localhost:端口/xxl-job-admin

2.部署执行器

  • 修改调用中心地址

    image-20221217205847949

  • 修改日志位置

    image-20221217205908942

  • maven打包后台方式启动 nohup java -jar xxl-job-executor-sample-springboot> tag-web.log 2>&1 &

3.秒杀系统接入xxl-job定时任务

  • 实现流程

    image-20221218094753997

  • 新增执行器

    image-20221217215317320

  • 新增任务管理器

    image-20221217215348322

  • 依赖

       <dependency>
            <groupId>com.xuxueli</groupId>
            <artifactId>xxl-job-core</artifactId>
            <version>2.3.0</version>
        </dependency>
       
  • yml配置

    # xxl-job配置
    xxl:
      job:
        admin:
          # 调度中心部署跟地址 [选填]:如调度中心集群部署存在多个地址则用逗号分隔。执行器将会使用该地址进行"执行器心跳注册"和"任务结果回调";为空则关闭自动注册;xxl-job后台管理界面的地址
          addresses: http://127.0.0.1:8091/xxl-job-admin
        executor:
          # 执行器注册 [选填]:优先使用该配置作为注册地址,为空时使用内嵌服务 ”IP:PORT“ 作为注册地址。从而更灵活的支持容器类型执行器动态IP和动态映射端口问题。
          address:
          # 执行器AppName [选填]:执行器心跳注册分组依据;为空则关闭自动注册
          appname: seckill-job
          # 执行器IP [选填]:默认为空表示自动获取IP,多网卡时可手动设置指定IP,该IP不会绑定Host仅作为通讯实用;地址信息用于 "执行器注册" 和 "调度中心请求并触发任务";
          ip:
          # 执行器端口号 [选填]:小于等于0则自动获取;默认端口为9999,单机部署多个执行器时,注意要配置不同执行器端口;
          port: 0
          # 执行器运行日志文件存储磁盘路径 [选填] :需要对该路径拥有读写权限;为空则使用默认路径;
          logpath: /Users/liubo/logs/test-job
          # 执行器日志文件保存天数 [选填] : 过期日志自动清理, 限制值大于等于3时生效; 否则, 如-1, 关闭自动清理功能;
          logretentiondays: 15
        # 执行器通讯TOKEN [选填]:非空时启用;
        accessToken:
    
  • config类

    @Slf4j
    @Configuration
    public class XxlJobConfig {
    
        @Value("${xxl.job.admin.addresses}")
        private String adminAddresses;
    
        @Value("${xxl.job.accessToken}")
        private String accessToken;
    
        @Value("${xxl.job.executor.address}")
        private String address;
    
        @Value("${xxl.job.executor.appname}")
        private String appName;
    
        @Value("${xxl.job.executor.ip}")
        private String ip;
    
        @Value("${xxl.job.executor.port}")
        private int port;
    
        @Value("${xxl.job.executor.logpath}")
        private String logPath;
    
        @Value("${xxl.job.executor.logretentiondays}")
        private int logRetentionDays;
    
    
        @Bean
        public XxlJobSpringExecutor xxlJobExecutor() {
            log.info("====xxl-job config init====");
            XxlJobSpringExecutor xxlJobSpringExecutor = new XxlJobSpringExecutor();
            xxlJobSpringExecutor.setAdminAddresses(adminAddresses);
            xxlJobSpringExecutor.setAppname(appName);
            xxlJobSpringExecutor.setIp(ip);
            xxlJobSpringExecutor.setPort(port);
            xxlJobSpringExecutor.setAccessToken(accessToken);
            xxlJobSpringExecutor.setLogPath(logPath);
            xxlJobSpringExecutor.setLogRetentionDays(logRetentionDays);
            return xxlJobSpringExecutor;
        }
    }
    
  • 定时任务

    @Slf4j
    @Service
    public class SeckillScheduled {
    
        @Autowired
        private SeckillService seckillService;
    
        @XxlJob("seckillScheduled")
        public void uploadSeckillSkuLatest3Days() {
            log.info("接收到定时任务触发");
            // 任务配置路由策略为第一台或者一致性hash可以保证分布式情况下,只会有一台机器执行一次此任务
            seckillService.uploadSeckillSkuLatest3Days();
        }
    }
    
  • 具体实现

    @Service
    public class SeckillServiceImpl implements SeckillService {
    
        @Autowired
        private StringRedisTemplate redisTemplate;
    
        @Autowired
        private ProductFeignService productFeignService;
    
        @Autowired
        private SeckillSessionFeignService seckillSessionFeignService;
    
        @Autowired
        private RedissonClient redissonClient;
    
    
        @Override
        public void uploadSeckillSkuLatest3Days() {
            R lates3DaySession = seckillSessionFeignService.getLates3DaySession();
            if (lates3DaySession.getCode() == 0) {
                List<SeckillSessionWithSkusVo> sessionData = lates3DaySession.getData(new TypeReference<List<SeckillSessionWithSkusVo>>() {});
                //1、缓存活动信息
                saveSessionInfos(sessionData);
    
                //2、缓存活动的关联商品信息
                saveSessionSkuInfo(sessionData);
            }
        }
    
        /**
         * 缓存活动的关联商品信息
         * @param sessions
         */
        private void saveSessionSkuInfo(List<SeckillSessionWithSkusVo> sessions) {
            for (SeckillSessionWithSkusVo session : sessions) {
                //准备hash操作,绑定hash
                BoundHashOperations<String, Object, Object> operations = redisTemplate.boundHashOps(SeckillConstant.SECKILL_CHARE_PREFIX);
                if (CollectionUtil.isNotEmpty(session.getRelationSkus())){
                    session.getRelationSkus().forEach(seckillSkuVo -> {
                        //生成随机码
                        String token = UUID.randomUUID().toString().replace("-", "");
                        String redisKey = seckillSkuVo.getPromotionSessionId().toString() + "-" + seckillSkuVo.getSkuId().toString();
                        if (!operations.hasKey(redisKey)) {
    
                            //缓存我们商品信息
                            SeckillSkuRedisTo redisTo = new SeckillSkuRedisTo();
                            Long skuId = seckillSkuVo.getSkuId();
                            //1、先查询sku的基本信息,调用远程服务
                            R info = productFeignService.getSkuInfo(skuId);
                            if (info.getCode() == 0) {
                                SkuInfoVo skuInfo = info.getData("skuInfo",new TypeReference<SkuInfoVo>(){});
                                redisTo.setSkuInfo(skuInfo);
                            }
    
                            //2、sku的秒杀信息
                            BeanUtils.copyProperties(seckillSkuVo,redisTo);
    
                            //3、设置当前商品的秒杀时间信息
                            redisTo.setStartTime(session.getStartTime().getTime());
                            redisTo.setEndTime(session.getEndTime().getTime());
    
                            //4、设置商品的随机码(防止恶意攻击)
                            redisTo.setRandomCode(token);
    
                            //序列化json格式存入Redis中
                            String seckillValue = JSON.toJSONString(redisTo);
                            operations.put(redisKey,seckillValue);
    
                            //如果当前这个场次的商品库存信息已经上架就不需要上架
                            //5、使用库存作为分布式Redisson信号量(限流)
                            // 使用库存作为分布式信号量
                            RSemaphore semaphore = redissonClient.getSemaphore(SeckillConstant.SKU_STOCK_SEMAPHORE + token);
                            // 商品可以秒杀的数量作为信号量
                            semaphore.trySetPermits(seckillSkuVo.getSeckillCount());
                        }
                    });
                }
            }
        }
    
        /**
         * 缓存活动信息
         * @param sessions
         */
        private void saveSessionInfos(List<SeckillSessionWithSkusVo> sessions) {
            for (SeckillSessionWithSkusVo session : sessions) {
                //获取当前活动的开始和结束时间的时间戳
                long startTime = session.getStartTime().getTime();
                long endTime = session.getEndTime().getTime();
    
                //存入到Redis中的key
                String key = SeckillConstant.SESSION_CACHE_PREFIX + startTime + "_" + endTime;
    
                //判断Redis中是否有该信息,如果没有才进行添加
                Boolean hasKey = redisTemplate.hasKey(key);
                //缓存活动信息
                if (!hasKey) {
                    //获取到活动中所有商品的skuId
                    if (CollectionUtil.isNotEmpty(session.getRelationSkus())){
                        List<String> skuIds = session.getRelationSkus().stream()
                                .map(item -> item.getPromotionSessionId() + "-" + item.getSkuId().toString()).collect(Collectors.toList());
                        redisTemplate.opsForList().leftPushAll(key, skuIds);
                    }
                }
            }
        }
    }
    

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/99709.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

[附源码]Nodejs计算机毕业设计基于疫情防控的超市管理系统Express(程序+LW)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程。欢迎交流 项目运行 环境配置&#xff1a; Node.js Vscode Mysql5.7 HBuilderXNavicat11VueExpress。 项目技术&#xff1a; Express框架 Node.js Vue 等等组成&#xff0c;B/S模式 Vscode管理前后端分…

Innodb存储引擎-表(约束、视图、物化视图、分区表)

文章目录约束(数据完整性)视图物化视图分区表概述分区类型子分区分区和性能在表和分区间交换数据约束(数据完整性) 关系型数据库系统和文件系统的一个不同点是&#xff0c;关系数据库本身能保证存储数据的完整性&#xff0c;不需要应用程序的控制&#xff0c;而文件系统一般需…

ArcGIS Pro 加载项(6)——样式符号属性对调

之前是已经通过Python构建脚本工具&#xff0c;实现了stylx文件的符号属性的对调。 ArcGIS Pro脚本工具&#xff08;12&#xff09;——样式符号属性对调_学学GIS的博客-CSDN博客为地类做样式符号匹配经常碰到这样的问题&#xff1a;属性表里面只有地类代码&#xff0c;但是做…

win10+VS2017+OpenGL ES3.0 环境配置 源码编译及示例运行

win10VS2017OpenGL ES3.0 环境配置 源码编译及示例运行 win10VS2017OpenGL ES3.0 环境配置 源码编译及示例运行 本人参考其他人的博客内容学习opengles3.0编程指南&#xff0c;并在win10系统上用VS2017对OpenGL ES3.0 进行了实际的环境配置及源码编译。 一、环境准备工作 1…

Java项目:SSM网上药品销售商城网站系统

作者主页&#xff1a;源码空间站2022 简介&#xff1a;Java领域优质创作者、Java项目、学习资料、技术互助 文末获取源码 项目介绍 本系统分为前后台&#xff0c;分为管理员与普通用户两种角色&#xff0c;前台由普通用户登录&#xff0c;后台由管理员登录&#xff1b; 管理员…

架构师必读 —— 逻辑模型(3)

逻辑思考总是从提问“为什么”开始 培养逻辑思考习惯的捷径之一&#xff0c;就是经常问自己“为什么”。无论收到什么信息&#xff0c;都应该试着问一句“为什么”。 举个例子&#xff0c;A公司收购了其他竞争公司。为什么会收购呢&#xff1f; 这其中隐藏着A公司的发展战略。另…

闲置物品交易系统

开发工具(eclipse/idea/vscode等)&#xff1a; 数据库(sqlite/mysql/sqlserver等)&#xff1a; 功能模块(请用文字描述&#xff0c;至少200字)&#xff1a; 基于55m闲置物品交易系统 网站前台&#xff1a;关于我们、联系我们、公告信息、闲置物品、求购信息 管理员功能&#xf…

多态的学习

目录什么是多态多态有啥限制条件吗&#xff1f;重写向下转型和向上转型向上转型向下转型多态的优点多态缺陷避免在构造方法中调用重写的方法什么是多态 多态的概念&#xff1a;就是去完成某个行为&#xff0c;当不同的对象去完成时会产生出不同的状态。 举个例子大家就知道了&…

vue router动态路由与路由的匹配

vue router动态路由与路由的匹配&#xff0c;路由使用正则语法 一、动态路由 1.1 新建一个 user.vue文件 在views文件夹&#xff0c;新建一个user.vue文件 <template><div>用户{{id}}</div> </template><script setup>import { useRoute } from…

SAP ABAP Algorithm 计算一组数据样本的常用统计值(最大值/最小值 /平均值/中位数/众数/总数/方差/标准差 )

SAP ABAP Algorithm 计算一组数据样本的常用统计值(最大值/最小值 /平均值/中位数/众数/总数/方差/标准差 ) 引言&#xff1a; 这是统计学常用统计值的 ABAP 实现&#xff0c;这些统计值可以用在一些统计分析型报表中。 关键字&#xff1a;SAP ABAP Algorithm 算法 统计值 文…

Pytest测试框架(4):conftest.py文件应用---实现数据共享

conftest.py文件&#xff1a; pytest中的fixture是pytest用于将测试前后进行预备&#xff0c;清理工作的代码分离出核心测试逻辑的一种机制。但是我们更加希望的是在一个测试套件中&#xff0c;能够共享fixture的机制&#xff0c;这样一个测试套件里面的所有测试点都能够共同使…

Innodb存储引擎-idb文件格式解析

文章目录ibd 文件格式解析idb文件page类型和格式(File Header & Trailer)FIL_PAGE_TYPE_FSP_HDR格式Extent Descriptor格式Extent Descriptor链表管理Inode page链表管理FIL_PAGE_INODE格式Segment inode链表管理FIL_PAGE_TYPE_XDESFIL_PAGE_INDEX格式记录存储格式compact …

免费分享一个SSM商城管理系统,很漂亮的

大家好&#xff0c;我是锋哥&#xff0c;看到一个不错的SSM商城管理系统&#xff0c;分享下哈。 项目介绍 这是基于SSM框架开发的项目&#xff0c;前端用户界面采用 HtmlcssJavaScriptAjax开发&#xff0c;后台管理页面采用Easyui技术开发。 项目展示 1、主界面 2、商品详…

JDK Stream流式API使用总结

前言 JDK是Java Development Kit英文首字母大写缩写&#xff0c;是 Sun 公司&#xff08;已被 Oracle 收购&#xff09;针对 Java 开发员的软件开发工具包。自从 Java 推出以来&#xff0c;JDK 已经成为使用最广泛的 Java SDK。从JDK8版本开始新增了Stream流式API的功能&#x…

单片机毕业设计题目选题推荐

文章目录1前言2 如何选题2.1 不要给自己挖坑2.2 难度把控2.3 如何命名题目3 单片机 嵌入式 选题大全3.1 嵌入式方向3.2 算法方向3.3 移动通信方向3.4 学长作品展示4 最后1前言 &#x1f947; 近期不少学弟学妹询问学长关于单片机和嵌入式相关的毕设选题&#xff0c;学长特意写…

城镇居民医疗网站

开发工具(eclipse/idea/vscode等)&#xff1a; 数据库(sqlite/mysql/sqlserver等)&#xff1a; 功能模块(请用文字描述&#xff0c;至少200字)&#xff1a; 模块划分&#xff1a;通知类型&#xff0c;通知信息&#xff0c;区域信息&#xff0c;人员信息&#xff0c;缴费类型&a…

Java基础:使用 Optional 优雅地解决判空问题

我是 ABin-阿斌&#xff1a;写一生代码&#xff0c;创一世佳话&#xff0c;筑一览芳华。如果小伙伴们觉得不错就一键三连吧~ 声明&#xff1a;原作者&#xff1a;樊亦凡&#xff1a;juejin.cn/post/6844904154075234318 文章目录1 . 前言2 . 认识 Optional 并使用2.1 Optional …

非零基础自学Golang 第9章 结构体 9.6 结构体内嵌

非零基础自学Golang 文章目录非零基础自学Golang第9章 结构体9.6 结构体内嵌9.6.1 初始化结构体内嵌9.6.2 内嵌匿名结构体第9章 结构体 9.6 结构体内嵌 Go语言的结构体内嵌是一种组合特性&#xff0c;使用结构体内嵌可构建一种面向对象编程思想中的继承关系。 结构体实例化后…

[附源码]Python计算机毕业设计Django文曦家教预约系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

PCB四层板、六层板层叠推荐设计,常见层叠方案优缺点

笔者电子信息专业硕士毕业&#xff0c;获得过多次电子设计大赛、大学生智能车、数学建模国奖&#xff0c;现就职于南京某半导体芯片公司&#xff0c;从事硬件研发&#xff0c;电路设计研究。对于学电子的小伙伴&#xff0c;深知入门的不易&#xff0c;特开次博客交流分享经验&a…