当前位置: 首页 > news >正文

常德网站开发公司世界500强企业排名表

常德网站开发公司,世界500强企业排名表,网页界面设计教案,网站seo分析报告案例缓存预热 为什么要做预热: 当活动真正开始时#xff0c;需要超高的并发访问活动相关信息 必须把必要的数据提前加载进redis 预热的策略: 在msg中写一个定时任务 每分钟扫描一遍card_game表 把(开始时间 当前时间) (开始时间 当前时间1分钟)的活动及相…缓存预热 为什么要做预热: 当活动真正开始时需要超高的并发访问活动相关信息 必须把必要的数据提前加载进redis 预热的策略: 在msg中写一个定时任务 每分钟扫描一遍card_game表 把(开始时间  当前时间) (开始时间  当前时间1分钟)的活动及相关信息放入redis 缓存预热流程: ​​​​​​​代码上需要取出满足条件的活动列表对每个活动查出相应的奖品放到令牌桶查出相应的活动策略放到Redis 1、查询1分钟内的活动  2、循环遍历活动列表挨个处理假设当前取出的是A 3、查询A相关的奖品列表及数量  4、根据总数量生成奖品相关的令牌桶 5、查询A相关的活动策略:抽奖次数、中奖次数等放入Redis 缓存体系 1)活动基本信息 k-v以活动id为key活动对象为value永不超时 redisUtil.set(RedisKeys.INFOgame.getId(),game,-1); 2)活动策略信息 使用hset以活动id为group用户等级为key策略值为value redisUtil.hset(RedisKeys.MAXGOAL game.getId(),r.getUserlevel(),r.getGoalTimes()); redisUtil.hset(RedisKeys.MAXENTER game.getId(),r.getUserlevel(),r.getEnterTimes()); 3)抽奖令牌桶 双端队列以活动id为key在活动时间段内随机生成时间戳做令牌有多少个奖品就生成多少个令牌。令牌即奖品发放的时间点。从小到大排序后从右侧入队。 redisUtil.rightPushAll(RedisKeys.TOKENS game.getId(),tokenList); 4)奖品映射信息 k-v , 以活动id_令牌为key奖品信息为value会员获取到令牌后如果令牌有效则用令牌token值来这里获取 奖品详细信息 redisUtil.set(RedisKeys.TOKEN game.getId() _token,cardProduct,expire); 5)令牌设计技巧  假设活动时间间隔太短奖品数量太多。那么极有可能产生的时间戳发生重复。 解决技巧:额外再附加一个随机因子。将 (时间戳 * 1000 3位随机数)作为令牌。抽奖时将抽中的令牌/1000 还原真实的时间戳。 //活动持续时间(ms) long duration end - start; long rnd start new Random().nextInt((int)duration); //为什么乘1000再额外加一个随机数呢? - 防止时间段奖品多时重复 long token rnd * 1000 new Random().nextInt(999); 6)中奖计数 k-v以活动id_用户id作为key中奖数为value利用redis原子性中奖后incr增加计数。 抽奖次数计数也是同样的道理 redisUtil.incr(RedisKeys.USERHITgameid_user.getId(),1); 7)中奖逻辑判断 : 抽奖时从令牌桶左侧出队和当前时间比较如果令牌时间戳小于等于当前时间令牌有效表示中奖。大于当前 时间则令牌无效将令牌还回从左侧压入队列。 代码开发 代码在msg项目下的GameTask里已集成Spring调度  看了下Spring调度 Scheduled内写循环时间下面的代码会定时执行 commons模块下有个RedisKeys已经定义了可用的Redis key前缀可以直接使用 接下来补全GameTask中的函数 先用QueryWrapper取到下一分钟所有的任务 // 获取当前时间 Date now new Date();// 查询将来1分钟内要开始的活动 QueryWrapperCardGame gameQueryWrapper new QueryWrapper(); // 开始时间大于当前时间 gameQueryWrapper.gt(starttime, now); // 小于等于当前时间1分钟 gameQueryWrapper.le(starttime, DateUtils.addMinutes(now, 1));ListCardGame list gameService.list(gameQueryWrapper); if (list.isEmpty()) {// 没有查到要开始的活动log.info(No upcoming games within the next minute.); } else {log.info(Found {} upcoming games., list.size()); }对于每个任务获取到要存入Redis中的信息 list.forEach(game - {// 活动开始时间long start game.getStarttime().getTime();// 活动结束时间long end game.getEndtime().getTime();// 计算活动结束时间到现在还有多少秒作为redis key过期时间long expire (end - now.getTime()) / 1000;// 活动持续时间mslong duration end - start;// 创建查询参数的MapMapString, Object queryMap new HashMap();queryMap.put(gameid, game.getId()); 先将基本信息存入Redis // 活动基本信息 game.setStatus(1); redisUtil.set(RedisKeys.INFO game.getId(), game, -1); log.info(Loaded game info: {}, {}, {}, {}, game.getId(), game.getTitle(), game.getStarttime(), game.getEndtime());把奖品放入map // 活动奖品信息 ListCardProductDto products gameLoadService.getByGameId(game.getId()); MapInteger, CardProduct productMap new HashMap(products.size()); products.forEach(p - productMap.put(p.getId(), p)); log.info(Loaded product types: {}, productMap.size());//奖品数量等配置信息 ListCardGameProduct gameProducts gameProductService.listByMap(queryMap); log.info(load bind product:{},gameProducts.size()); 令牌桶创建然后token存入Redis // 令牌桶 ListLong 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);// 以令牌做key对应的商品为value创建redis缓存log.info(Token - Game: {} - {}, token / 1000, productMap.get(cgp.getProductid()).getName());// Token到实际奖品之间建立映射关系redisUtil.set(RedisKeys.TOKEN game.getId() _ token, productMap.get(cgp.getProductid()), expire);} });// 排序后放入redis队列 Collections.sort(tokenList); log.info(Loaded tokens: {}, tokenList);// 从右侧压入队列从左到右时间戳逐个增大 redisUtil.rightPushAll(RedisKeys.TOKENS game.getId(), tokenList); redisUtil.expire(RedisKeys.TOKENS game.getId(), expire);接着将策略存入Redis // 奖品策略配置信息 ListCardGameRules rules gameRulesService.listByMap(queryMap); // 遍历策略存入redis hset rules.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());log.info(Loaded rules: level{}, enter{}, goal{}, rate{},r.getUserlevel(), r.getEnterTimes(), r.getGoalTimes(), r.getRandomRate()); }); redisUtil.expire(RedisKeys.MAXGOAL game.getId(), expire); redisUtil.expire(RedisKeys.MAXENTER game.getId(), expire); redisUtil.expire(RedisKeys.RANDOMRATE game.getId(), expire);写完运行发现每隔一分钟尝试将活动信息写入缓存 然后写了个缓存接口来测试代码从Redis里取数据即可 GetMapping(/info/{gameid}) ApiOperation(value 缓存信息) ApiImplicitParams({ApiImplicitParam(namegameid,value 活动id,example 1,required true) }) public ApiResult info(PathVariable int gameid) {MapString, Object resMap new LinkedHashMap();MapString, Object tokenMap new LinkedHashMap();Object gameInfo redisUtil.get(RedisKeys.INFO gameid);MapObject, Object maxGoalMap redisUtil.hmget(RedisKeys.MAXGOAL gameid);MapObject, Object maxEnterMap redisUtil.hmget(RedisKeys.MAXENTER gameid);ListObject tokenList redisUtil.lrange(RedisKeys.TOKENS gameid, 0, -1);resMap.put(RedisKeys.INFO gameid, gameInfo);resMap.put(RedisKeys.MAXGOAL gameid, maxGoalMap);resMap.put(RedisKeys.MAXENTER gameid, maxEnterMap);for (Object item : tokenList) {Object tokenData redisUtil.get(RedisKeys.TOKEN gameid _ item.toString());Long key Long.valueOf(item.toString());Date date new Date(key / 1000);SimpleDateFormat dateFormat new SimpleDateFormat(yyyy-MM-dd HH:mm:ss.SSS);String formattedDate dateFormat.format(date);tokenMap.put(formattedDate, tokenData);}resMap.put(RedisKeys.TOKENS gameid, tokenMap);return new ApiResult(200, 缓存信息, resMap); }运行测试 在后台数据库启动一个近期活动 查看Redis
http://www.w-s-a.com/news/716475/

相关文章:

  • 安通建设有限公司网站东莞地铁app
  • 群晖nas做网站滨州教育平台 网站建设
  • 住房城市乡建设部网站装修平台有哪些
  • 小米网站 用什么做的深圳广告公司前十强
  • 勤哲网站开发视频瑞安 网站建设培训
  • 有个蓝色章鱼做标志的网站高端的网站建设怎么做
  • 建站网址导航hao123html网页设计实验总结
  • 西宁市网站建设价格丽水集团网站建设
  • 长宁怎么做网站优化好本机怎么放自己做的网站
  • 诚信网站备案中心网站字体怎么设置
  • 企业网站建设费是无形资产吗佛山网站建设哪个好点
  • 网站建设就业方向国开行网站毕业申请怎么做
  • 创建一个网站的费用wordpress 4.0 安装
  • 会员登录系统网站建设dw软件是做什么用的
  • 手机网站被做跳转长沙网上购物超市
  • 网站建设中网站需求分析设计网站推荐html代码
  • 容易收录的网站台州汇客网站建设
  • 企业网站源码百度网盘下载网站备案号如何查询密码
  • 个人网站建设课程宣传栏制作效果图
  • 自己做的网站能上传吗网上做彩票网站排名
  • 教育培训网站模板下载自己做商务网站有什么利弊
  • 平面设计公司网站兰州室内设计公司排名
  • 个人工作室注册条件温州seo结算
  • 360免费建站系统中国建设银行官网站黄金部王毅
  • 罗源福州网站建设个体户可以网站备案吗
  • 网站开发 专有名词pc网站建设和推广
  • 上海部道网站 建设conoha wordpress
  • 手机测评做视频网站宝塔可以做二级域名网站么
  • 代理公司注册济南重庆seo优化效果好
  • 佛山市骏域网站建设专家徐州网站建设价格