【抽奖项目】|第二篇

前言:

        高并发的活动预热肯定不可以在数据库操作,需要redis,特别是这种秒杀活动更是需要注意,所以可以在高并发的前夕先进行活动预热。

 思路:

       1、 通过定时任务调度每分钟查询数据库也没有需要预热的活动

        2、采用分布式锁防止任务重复调度

        3、查询到预热活动需要信息全部进行redis存储

        4、生成令牌桶

                  细节:生成总奖品个数个令牌

                             每个令牌生成开始到结束时间的一个随机数

                              乘上1000,在额外加上一个三位数的随机数  ------防止奖品过多令牌重复

                              把令牌放入令牌桶

                              设置令牌和奖品的关系

        5、先按照时间大小排序,在压入redis

        6、改变预热状态

    @Scheduled(cron = "0 * * * * ?")public void execute() {//TODO 缓存预热// 获取当前时间的Calendar实例Calendar calendar = Calendar.getInstance();// 清除毫秒部分calendar.set(Calendar.MILLISECOND, 0);// 获取不带毫秒的Date对象Date now = calendar.getTime();//分布式锁,防止重复启动任务if (!redisUtil.setNx("game_task_"+now.getTime(),1,60L)){log.info("task started by another server!");return;}//查询将来1分钟内要开始的活动QueryWrapper<CardGame> gameQueryWrapper = new QueryWrapper<>();//开始时间大于当前时间gameQueryWrapper.gt("starttime",now);//小于等于(当前时间+1分钟)gameQueryWrapper.le("starttime",DateUtils.addMinutes(now,1));List<CardGame> list = gameService.list(gameQueryWrapper);if(list.size() == 0){//没有查到要开始的活动log.info("没有查到要开始的活动");return;}log.info("需要缓存预热的活动个数:{}",list.size());//有相关活动数据,则将活动数据预热,进redislist.forEach(game ->{//活动开始时间long start = game.getStarttime().getTime();//活动结束时间long end = game.getEndtime().getTime();//计算活动结束时间到现在还有多少秒,作为redis key过期时间long expire = (end - now.getTime())/1000;
//            long expire = -1; //永不过期//活动持续时间(ms)long duration = end - start;Map queryMap = new HashMap();queryMap.put("gameid",game.getId());//活动基本信息game.setStatus(1);redisUtil.set(RedisKeys.INFO+game.getId(),game,-1);log.info("活动ID:{},名称:{},开始:{},结束{}", game.getId(),game.getTitle(),game.getStarttime(),game.getEndtime());//活动奖品信息List<CardProductDto> products = gameLoadService.getByGameId(game.getId());Map<Integer,CardProduct> productMap = new HashMap<>(products.size());products.forEach(p -> {productMap.put(p.getId(),p);});//奖品数量等配置信息List<CardGameProduct> gameProducts = gameProductService.listByMap(queryMap);//令牌桶List<Long> tokenList = new ArrayList();gameProducts.forEach(cgp ->{//生成amount个start到end之间的随机时间戳做令牌for (int i = 0; i < cgp.getAmount(); i++) {long rnd = start + new Random().nextInt((int)duration);//为什么乘1000,再额外加一个随机数呢? - 防止时间段奖品多时重复//记得取令牌判断时间时,除以1000,还原真正的时间戳long token = rnd * 1000 + new Random().nextInt(999);//将令牌放入令牌桶tokenList.add(token);//token到实际奖品之间建立映射关系redisUtil.set(RedisKeys.TOKEN + game.getId() +"_"+token,productMap.get(cgp.getProductid()),expire);}});//排序后放入redis队列Collections.sort(tokenList);log.info("load tokens:{}",tokenList);//从右侧压入队列,从左到右,时间戳逐个增大redisUtil.rightPushAll(RedisKeys.TOKENS + game.getId(),tokenList);redisUtil.expire(RedisKeys.TOKENS + game.getId(),expire);//奖品策略配置信息List<CardGameRules> rules = gameRulesService.listByMap(queryMap);//遍历策略,存入redis hsetrules.forEach(r -> {redisUtil.hset(RedisKeys.MAXGOAL +game.getId(),r.getUserlevel()+"",r.getGoalTimes());redisUtil.hset(RedisKeys.MAXENTER +game.getId(),r.getUserlevel()+"",r.getEnterTimes());redisUtil.hset(RedisKeys.RANDOMRATE +game.getId(),r.getUserlevel()+"",r.getRandomRate());});redisUtil.expire(RedisKeys.MAXGOAL +game.getId(),expire);redisUtil.expire(RedisKeys.MAXENTER +game.getId(),expire);redisUtil.expire(RedisKeys.RANDOMRATE +game.getId(),expire);//活动状态变更为已预热,禁止管理后台再随便变动game.setStatus(1);gameService.updateById(game);});}

                                

        

        

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

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

相关文章

异或和之和 第十四届蓝桥杯大赛软件赛省赛C/C++ 大学 A 组

异或和之和 题目来源 第十四届蓝桥杯大赛软件赛省赛C/C++ 大学 A 组 原题链接 蓝桥杯 异或和之和 https://www.lanqiao.cn/problems/3507/learning/ 问题描述 问题分析 要点1:异或运算 概念 异或(Exclusive OR,简称 XOR)是一种数学运算符,常用于逻辑运算与计算机…

从零到一:如何系统化封装并发布 React 组件库到 npm

1. 项目初始化 1.1 创建项目 首先&#xff0c;创建一个新的项目目录并初始化 package.json 文件。 mkdir my-component-library cd my-component-library npm init -y1.2 安装依赖 安装开发所需的依赖项&#xff0c;如构建工具、测试框架等。 npm install --save-dev webp…

现代互联网网络安全与操作系统安全防御概要

现阶段国与国之间不用对方路由器&#xff0c;其实是有道理的&#xff0c;路由器破了&#xff0c;内网非常好攻击&#xff0c;内网共享开放端口也非常多&#xff0c;更容易攻击。还有些内存系统与pe系统自带浏览器都没有javascript脚本功能&#xff0c;也是有道理的&#xff0c;…

2025-03-12 学习记录--C/C++-PTA 习题8-4 报数

合抱之木&#xff0c;生于毫末&#xff1b;九层之台&#xff0c;起于累土&#xff1b;千里之行&#xff0c;始于足下。&#x1f4aa;&#x1f3fb; 一、题目描述 ⭐️ 习题8-4 报数 报数游戏是这样的&#xff1a;有n个人围成一圈&#xff0c;按顺序从1到n编好号。从第一个人开…

【js逆向】某预约票网站 (webpack技术)

1、查看数据包 calendar是需要的数据包&#xff0c;看下它的请求参数。 accTimes参数加密&#xff0c;_times是时间戳。 2、全局搜索 accTimes 关键字 3、n的定义 4、把整个js代码复制下来&#xff0c;应用到了webpack技术&#xff0c;图中的Q是n

前端模块管理新思路:如何使用 Import Maps

前言 前端开发中&#xff0c;我们常常需要使用各种库和模块来构建功能丰富的应用。在传统方式中&#xff0c;管理这些库和模块的引用可能会有些繁琐。 幸运的是&#xff0c;Import Maps 的出现为我们提供了一种更简洁和高效的解决方案。今天我们就来聊聊如何使用 Import Maps。…

AI模型的构建过程是怎样的(下)

你好,我是舒旻。 上节课,我们讲了一个模型构建的前 2 个环节,模型设计和特征工程。今天,我们继续来讲模型构建的其他 3 个环节,说说模型训练、模型验证和模型融合中,算法工程师的具体工作内容,以及 AI 产品经理需要掌握的重点。 模型训练 模型训练是通过不断训练、验证…

人工智能混合编程实践:Python ONNX进行图像超分重建

人工智能混合编程实践:Python ONNX进行图像超分重建 前言相关介绍Python简介ONNX简介图像超分辨率重建简介应用场景前提条件实验环境项目结构使用Python ONNX进行图像超分重建sr_py_infer.py参考文献前言 由于本人水平有限,难免出现错漏,敬请批评改正。更多精彩内容,可点击…

视频理解之Actionclip(论文宏观解读)

配合解读代码解读 1.研究背景 1. 视频行为识别的重要性 视频行为识别是视频理解领域的核心任务之一&#xff0c;旨在通过分析视频内容来识别和分类其中的人物行为或活动。这一任务在多个领域具有重要的应用价值&#xff0c;例如智能监控、人机交互、自动驾驶、医疗健康等。随…

【mysql】centOS7安装mysql详细操作步骤!

【mysql】centOS7安装mysql详细操作步骤&#xff01;—通过tar包方式 需要 root 权限&#xff0c;使用 root 用户进行命令操作。 1. 查看 CentOS 版本 cat /etc/redhat-release2. 安装rpm包&#xff0c;以8为例 打开 MySQL 官方 yum 仓库网站&#xff0c;获取与当前 CentOS …

【网络编程】事件选择模型

十、基于I/O模型的网络开发 10.9 事件选择模型 10.0.1 基本概念 事件选择(WSAEventSelect) 模型是另一个有用的异步 I/O 模型。和 WSAAsyncSelect 模 型类似的是&#xff0c;它也允许应用程序在一个或多个套接字上接收以事件为基础的网络事件通知&#xff0c;最 主要的差别在…

STM32 F407ZGT6开发板

#ifndef _tftlcd_H #define _tftlcd_H #include "system.h" //定义LCD彩屏的驱动类型 可根据自己手上的彩屏背面型号来选择打开哪种驱动 //#def…

江科大51单片机笔记【15】直流电机驱动(PWM)

写在前言 此为博主自学江科大51单片机&#xff08;B站&#xff09;的笔记&#xff0c;方便后续重温知识 在后面的章节中&#xff0c;为了防止篇幅过长和易于查找&#xff0c;我把一个小节分成两部分来发&#xff0c;上章节主要是关于本节课的硬件介绍、电路图、原理图等理论…

鸿蒙模拟器运行NDK项目失败 9568347

鸿蒙编译NDK项目 模拟器运行NDK项目失败 9568347 23:32:17.572: $ hdc file send D:\study\hongmeng\MyTestNdk\entry\build\default\outputs\default\entry-default-unsigned.hap "data/local/tmp/9fff4611338a424bb31b521bdc3555af" in 30 ms 23:32:17.651: $ hd…

uniapp+Vue3 开发小程序的下载文件功能

小程序下载文件&#xff0c;可以先预览文件内容&#xff0c;然后在手机上打开文件的工具中选择保存。 简单示例&#xff1a;&#xff08;复制到HBuilder直接食用即可&#xff09; <template><view class"container-detail"><view class"example…

电机控制常见面试问题(九)

文章目录 一、谈谈电机死区时间1.死区时间过短的后果&#xff1a;2.如何判断死区时间不足?3.解决方案 二、请描述对实时操作系统&#xff08;RTOS&#xff09;的理解三.解释FOC算法的原理并比较与其他无刷电机控制算法的优劣四.什么是电机堵转&#xff0c;如何避免电机堵转五.…

【分布式】聊聊分布式id实现方案和生产经验

对于分布式Id来说&#xff0c;在面试过程中也是高频面试题&#xff0c;所以主要针对分布式id实现方案进行详细分析下。 应用场景 对于无论是单机还是分布式系统来说&#xff0c;对于很多场景需要全局唯一ID&#xff0c; 数据库id唯一性日志traceId 可以方便找到日志链&#…

【性能测试】Jmeter如何做一份测试报告(3)

本篇文章主要介绍Jmeter中下载插件&#xff08;Jmeter Plugins&#xff09; 如何使用监听器插件&#xff0c;线程组插件&#xff0c;梯度压测线程组 测试报告需要去关注的数据&#xff0c;怎么看测试报告图表 目录 一&#xff1a;插件下载 1&#xff1a;下载地址 2&#xff…

cocos creator使用mesh修改图片为圆形,减少使用mask,j减少drawcall,优化性能

cocos creator版本2.4.11 一个mask占用drawcall 3个以上&#xff0c;针对游戏中技能图标&#xff0c;cd,以及多玩家头像&#xff0c;是有很大优化空间 1.上代码&#xff0c;只适合单独图片的&#xff0c;不适合在图集中的图片 const { ccclass, property } cc._decorator;c…

AI重构SEO关键词布局

内容概要 在搜索引擎优化&#xff08;SEO&#xff09;领域&#xff0c;AI技术的深度应用正在颠覆传统关键词布局逻辑。通过机器学习算法与语义分析模型&#xff0c;智能系统能够实时解析海量搜索数据&#xff0c;构建动态词库并精准捕捉用户意图。相较于依赖人工经验的关键词筛…