【抽奖项目】|第二篇

前言:

        高并发的活动预热肯定不可以在数据库操作,需要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.rhkb.cn/news/32505.html

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

相关文章

DataWhale 大语言模型 - 语言模型发展历程

大语言模型 LLMBook 项目背景 本课程围绕中国人民大学高瓴人工智能学院赵鑫教授团队出品的《大语言模型》书籍展开&#xff0c;覆盖大语言模型训练与使用的全流程&#xff0c;从预训练到微调与对齐&#xff0c;从使用技术到评测应用&#xff0c;帮助学员全面掌握大语言模型的…

C#带有设备仿真功能串口调试助手

本文档介绍一种方法,可以用来仿真串口设备。这样调试PLC程序时可以在没有仪器时用于测试程序的运行。详细代码见: https://download.csdn.net/download/qq_34047402/90477066 C#带有设备仿真功能串口调试助手资源-CSDN文库 步骤如下: 1.把串口设备接收和发送仿真数据放到一…

本地部署 OpenManus 保姆级教程(Windows 版)

一、环境搭建 我的电脑是Windows 10版本&#xff0c;其他的没尝试&#xff0c;如果大家系统和我的不一致&#xff0c;请自行判断&#xff0c;基本上没什么大的出入啊。 openManus的Git地址&#xff1a;https://github.com/mannaandpoem/OpenManus 根据官网的两种安装推荐方式如…

01 | Go 项目开发极速入门课介绍

提示&#xff1a; 所有体系课见专栏&#xff1a;Go 项目开发极速入门实战课。 你好&#xff0c;欢迎学习本课程。本课程是一个 Go 项目开发极速入门课程。旨在帮助刚学习完 Go 基础语法的 Go 开发者&#xff0c;快速掌握如何开发一个功能相对全面的 Go 项目。 根据课程设计目标…

使用 Elastic-Agent 或 Beats 将 Journald 中的 syslog 和 auth 日志导入 Elastic Stack

作者&#xff1a;来自 Elastic TiagoQueiroz 我们在 Elastic 一直努力将更多 Linux 发行版添加到我们的支持矩阵中&#xff0c;现在 Elastic-Agent 和 Beats 已正式支持 Debian 12&#xff01; 本文演示了我们正在开发的功能&#xff0c;以支持使用 Journald 存储系统和身份验…

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

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

【Linux】:封装线程

朋友们、伙计们&#xff0c;我们又见面了&#xff0c;本期来给大家带来封装线程相关的知识点&#xff0c;如果看完之后对你有一定的启发&#xff0c;那么请留下你的三连&#xff0c;祝大家心想事成&#xff01; C 语 言 专 栏&#xff1a;C语言&#xff1a;从入门到精通 数据结…

全球领先的光学方案设计公司:倚光科技

在光学技术革新的浪潮中&#xff0c;倚光&#xff08;深圳&#xff09;科技有限公司以创新者的姿态迅速崛起&#xff0c;成为全球光学领域的标杆企业。自 2021 年成立以来&#xff0c;公司始终聚焦纳米光学技术研发与超精密加工&#xff0c;凭借顶尖的技术实力和前瞻性的市场布…

2.2.3 TCP—UDP-QUIC

文章目录 2.2.3 TCP—UDP-QUIC1. TCP如何做到可靠性传输1. ACK机制2. 重传机制3. 序号机制4. 窗口机制5. 流量机制6. 带宽机制 2. tcp和udp如何选择1. tcp和udp格式对比2. ARQ协议&#xff08;Automatic Repeat reQuest&#xff0c;自动重传请求&#xff09;1. ARQ协议的主要类…

【动手实验】TCP 连接的建立与关闭抓包分析

本文是基于知识星球程序员踩坑案例分享中的作业进行的复现和总结&#xff0c;借此加深对 TCP 协议的理解&#xff0c; 原文参见TCP 连接的建立和关闭 —— 强烈建议新手看看。 实验环境 这里使用两台位于同一子网的腾讯云服务器&#xff0c;IP 分别是 node2&#xff08;172.1…

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

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

基于LabVIEW的脚本化子VI动态生成

该示例展示了一种利用LabVIEW VI脚本&#xff08;VI Scripting&#xff09;技术&#xff0c;通过程序化方式动态生成并替换子VI的解决方案。核心逻辑为&#xff1a;基于预定义的模板VI&#xff0c;根据用户选择的数学操作&#xff08;加法或乘法&#xff09;&#xff0c;自动生…

Debian系统grub新增启动项

参考链接 给grub添加自定义启动项_linux grub定制 启动项名称自定义-CSDN博客 www.cnblogs.com 1. boot里面的grub.cfg 使用vim打开boot里面的grub.cfg sudo vim /boot/grub/grub.cfg 这时候会看到文件最上方的提示 2. 真正配置grub的文件 从刚才看到的文件提示中&#x…

ctfhub-web-SSRF通过攻略

1.URL Bypass 打开题目 请求的URL中必须包含http://notfound.ctfhub.com&#xff0c;使用来绕过即可 /?urlhttp://notfound.ctfhub.com127.0.0.1/flag.php 成功获得flag 2.数字IP Bypass 开启题目 发现127以及172被过滤了 尝试别的绕过 127.0.0.1–>localhost 127.0…

C语言(23)

字符串函数 11.strstr函数 1.1函数介绍&#xff1a; 头文件&#xff1a;string.h char *strstr ( const char * str1,const char *str2); 作用&#xff1a;在一个字符串&#xff08;str1&#xff09;中寻找另外一个字符串&#xff08;str2&#xff09;是否出现过 如果找到…

uniapp+Vue3 组件之间的传值方法

一、父子传值&#xff08;props / $emit 、ref / $refs&#xff09; 1、props / $emit 父组件通过 props 向子组件传递数据&#xff0c;子组件通过 $emit 触发事件向父组件传递数据。 父组件&#xff1a; // 父组件中<template><view class"container">…

晨控CK-FR08与汇川H5U系列PLC配置EtherNet/IP通讯连接手册

晨控CK-FR08与汇川H5U系列PLC配置EtherNet/IP通讯连接手册 晨控CK-FR08系列作为晨控智能工业级别RFID读写器,支持大部分工业协议如RS232、RS485、以太网。支持工业协议Modbus RTU、Modbus TCP、Profinet、EtherNet/lP、EtherCat以及自由协议TCP/IP等。 本期主题&#xff1a;围…

BLDC直流无刷电机转速电流双闭环调速MATLAB仿真

微♥&#xff1a;“电击小子程高兴的MATLAB小屋”获取巨额优惠 1.模型简介 本仿真模型基于MATLAB/Simulink&#xff08;版本MATLAB 2017Ra&#xff09;软件。建议采用matlab2017 Ra及以上版本打开。&#xff08;若需要其他版本可联系代为转换&#xff09; 2.仿真算法&#x…

Windows 11下Git Bash执行cURL脚本400问题、CMD/PowerShell不能执行多行文本等问题记录及解决方案

问题 在Postman里可成功执行的POST请求&#xff1a; 找到Postman的Code 因为cURL基本上算是行业标准&#xff0c;所以Postman默认选中cURL&#xff0c;支持切换不同的开发语言&#xff1a; 点击上图右上角的复制按钮&#xff0c;得到cURL脚本。 Windows 11家庭版&#xff…

4个 Vue 路由实现的过程

大家好&#xff0c;我是大澈&#xff01;一个喜欢结交朋友、喜欢编程技术和科技前沿的老程序员&#x1f468;&#x1f3fb;‍&#x1f4bb;&#xff0c;关注我&#xff0c;科技未来或许我能帮到你&#xff01; Vue 路由相信朋友们用的都很熟了&#xff0c;但是你知道 Vue 路由…