范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

请勿过度依赖Redis的过期监听

  Redis 过期监听场景
  业务中有类似等待一定时间之后执行某种行为的需求 , 比如 30 分钟之后关闭订单 . 网上有很多使用 Redis 过期监听的 Demo , 但是其实这是个大坑 , 因为 Redis 不能确保 key 在指定时间被删除 , 也就造成了通知的延期 . 不多说 , 跑个测试 测试情况
  先说环境 , redis 运行在 Docker 容器中 , 分配了 一个 cpu 以及 512MB 内存, 在 Docker 中执行  redis-benchmark -t set -r 100000 -n 1000000   结果如下:====== SET ======   1000000 requests completed in 171.03 seconds   50 parallel clients   3 bytes payload   keep alive: 1   host configuration "save": 3600 1 300 100 60 10000   host configuration "appendonly": no   multi-thread: no
  其实这里有些不严谨  benchmark   线程不应该在 Docker 容器内部运行 . 跑分的时候大概 benchmark 和 redis 主线程各自持有 50%CPU
  测试代码如下: @Service @Slf4j public class RedisJob {     @Autowired     private StringRedisTemplate stringRedisTemplate;      public DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");     public LocalDateTime end = LocalDateTime.of(LocalDate.of(2020, 5, 12), LocalTime.of(8, 0));      @Scheduled(cron = "0 56 * * * ?")     public void initKeys() {         LocalDateTime now = LocalDateTime.now();         ValueOperations operations = stringRedisTemplate.opsForValue();         log.info("开始设置key");         LocalDateTime begin = now.withMinute(0).withSecond(0).withNano(0);         for (int i = 1; i < 17; i++) {             setExpireKey(begin.plusHours(i), 8, operations);         }         log.info("设置完毕: " + Duration.between(now, LocalDateTime.now()));     }      private void setExpireKey(LocalDateTime expireTime, int step, ValueOperations operations) {         LocalDateTime localDateTime = LocalDateTime.now().withNano(0);         String nowTime = dateTimeFormatter.format(localDateTime);         while (expireTime.getMinute() < 55) {             operations.set(nowTime + "@" + dateTimeFormatter.format(expireTime), "A", Duration.between(expireTime, LocalDateTime.now()).abs());             expireTime = expireTime.plusSeconds(step);         }     } }
  大概意思就是每小时 56 分的时候 , 会增加一批在接下来 16 小时过期的 key , 过期时间间隔 8 秒 , 且过期时间都在 55 分之前 @Slf4j @Component public class RedisKeyExpirationListener extends KeyExpirationEventMessageListener {      public RedisKeyExpirationListener(RedisMessageListenerContainer listenerContainer) {         super(listenerContainer);     }      public DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");     @Autowired     private StringRedisTemplate stringRedisTemplate;       @Override     public void onMessage(Message message, byte[] pattern) {         String keyName = new String(message.getBody());         LocalDateTime parse = LocalDateTime.parse(keyName.split("@")[1], dateTimeFormatter);         long seconds = Duration.between(parse, LocalDateTime.now()).getSeconds();         stringRedisTemplate.execute((RedisCallback) connection -> {             Long size = connection.dbSize();             log.info("过期key:" + keyName + " ,当前size:" + size + " ,滞后时间" + seconds);             return null;         });     } }
  这里是监测到过期之后打印当前的 dbSize 以及滞后时间 @Bean public RedisMessageListenerContainer configRedisMessageListenerContainer(RedisConnectionFactory connectionFactory) {     ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();     executor.setCorePoolSize(100);     executor.setMaxPoolSize(100);     executor.setQueueCapacity(100);     executor.setKeepAliveSeconds(3600);     executor.setThreadNamePrefix("redis");     // rejection-policy:当pool已经达到max size的时候,如何处理新任务     // CALLER_RUNS:不在新线程中执行任务,而是由调用者所在的线程来执行     executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());     executor.initialize();     RedisMessageListenerContainer container = new RedisMessageListenerContainer();     // 设置Redis的连接工厂     container.setConnectionFactory(connectionFactory);     // 设置监听使用的线程池     container.setTaskExecutor(executor);     // 设置监听的Topic     return container; }
  设置 Redis 的过期监听 以及线程池信息 ,
  最后的测试结果是当 key 数量小于 1 万的时候 , 基本上都可以在 10s 内完成过期通知 , 但是如果数量到 3 万 , 就有部分 key 会延迟 120s . 顺便贴一下我最新的日志 2020-05-13 22:16:48.383  : 过期key:2020-05-13 11:56:02@2020-05-13 22:14:08 ,当前size:57405 ,滞后时间160 2020-05-13 22:16:49.389  : 过期key:2020-05-13 11:56:02@2020-05-13 22:14:32 ,当前size:57404 ,滞后时间137 2020-05-13 22:16:49.591  : 过期key:2020-05-13 10:56:02@2020-05-13 22:13:20 ,当前size:57403 ,滞后时间209 2020-05-13 22:16:50.093  : 过期key:2020-05-13 20:56:00@2020-05-13 22:12:32 ,当前size:57402 ,滞后时间258 2020-05-13 22:16:50.596  : 过期key:2020-05-13 07:56:03@2020-05-13 22:13:28 ,当前size:57401 ,滞后时间202 2020-05-13 22:16:50.697  : 过期key:2020-05-13 20:56:00@2020-05-13 22:14:32 ,当前size:57400 ,滞后时间138 2020-05-13 22:16:50.999  : 过期key:2020-05-13 19:56:00@2020-05-13 22:13:44 ,当前size:57399 ,滞后时间186 2020-05-13 22:16:51.199  : 过期key:2020-05-13 20:56:00@2020-05-13 22:14:40 ,当前size:57398 ,滞后时间131 2020-05-13 22:16:52.205  : 过期key:2020-05-13 15:56:01@2020-05-13 22:16:24 ,当前size:57397 ,滞后时间28 2020-05-13 22:16:52.808  : 过期key:2020-05-13 06:56:03@2020-05-13 22:15:04 ,当前size:57396 ,滞后时间108 2020-05-13 22:16:53.009  : 过期key:2020-05-13 06:56:03@2020-05-13 22:16:40 ,当前size:57395 ,滞后时间13 2020-05-13 22:16:53.110  : 过期key:2020-05-13 20:56:00@2020-05-13 22:14:56 ,当前size:57394 ,滞后时间117 2020-05-13 22:16:53.211  : 过期key:2020-05-13 06:56:03@2020-05-13 22:13:44 ,当前size:57393 ,滞后时间189 2020-05-13 22:16:53.613  : 过期key:2020-05-13 15:56:01@2020-05-13 22:12:24 ,当前size:57392 ,滞后时间269 2020-05-13 22:16:54.317  : 过期key:2020-05-13 15:56:01@2020-05-13 22:16:00 ,当前size:57391 ,滞后时间54 2020-05-13 22:16:54.517  : 过期key:2020-05-13 18:56:00@2020-05-13 22:15:44 ,当前size:57390 ,滞后时间70 2020-05-13 22:16:54.618  : 过期key:2020-05-13 21:56:00@2020-05-13 22:14:24 ,当前size:57389 ,滞后时间150 2020-05-13 22:16:54.819  : 过期key:2020-05-13 17:56:00@2020-05-13 22:14:40 ,当前size:57388 ,滞后时间134 2020-05-13 22:16:55.322  : 过期key:2020-05-13 10:56:02@2020-05-13 22:13:52 ,当前size:57387 ,滞后时间183 2020-05-13 22:16:55.423  : 过期key:2020-05-13 07:56:03@2020-05-13 22:14:16 ,当前size:57386 ,滞后时间159
  可以看到 , 当数量到达 5 万的时候 , 大部分都已经滞后了两分钟 , 对于业务方来说已经完全无法忍受了 总结
  可能到这里 , 你会说 Redis 给你挖了一个大坑 , 但其实这些都在文档上写的明明白白 How Redis expires keys:https://redis.io/commands/expire#how-redis-expires-keys Timing of expired events:https://redis.io/topics/notifications#timing-of-expired-events
  尤其是在 Timing of expired events 中 , 明确的说明了 "Basically  expired   events are generated when the Redis server deletes the key and not when the time to live theoretically reaches the value of zero.", 这两个文章读下来你会感觉 , 卧槽 Redis 的过期策略其实也挺"Low"的
  当我初写自己的开源项目的时候就在订单自动过期采用的就是监听redis自动过期key的方法,还好当时想了更好的办法,不然就真的入坑了
  转载:https://cloud.tencent.com/developer/article/1762278
S24赛季更新时间公布,新版本内容曝光,马可波罗退出历史舞台在昨天官方官宣李逍遥这款皮肤上架同时还官宣了此次上架的很多活动,并且还告诉了大家本赛季将会推迟一周,那么本赛季的战令原本结束的日期为6月13日,现在已经推到了6月20日,这也就意味索尼新PS5及游戏手柄近日秘鲁注册今日消息,索尼PS5游戏主机已在国内发售,搭载AMD定制芯片Zen2架构CPURDNA2架构GPU,采用台积电7nm工艺。据外媒报道,代号为CFI1015A的新PS5近日在秘鲁成功游戏日历诛神记删档测试iOS畅销榜Top10总收入超7300万元导语游戏日历旨在记录游戏圈内每日大事,为游戏行业发展增添脚注。壹周游闻回顾1。5月23日29日,iOS畅销榜Top10游戏总收入超7300万元人民币,环比上周增长约2,这也是该数据能调节灵敏度和键程的游戏手柄北通阿修罗3有线版体验作为一名游戏发烧友,我从FCMDSFCDCPSXBOX到现在的PS4一路走来,可以说对于手柄有着难以割舍的情感,哪怕在电脑上玩,我依然觉得手柄比键盘更加带劲。说起手柄的品牌,相信大食人鲨游戏评测前言那是一条鲨鱼,我看着它从海底跃出扑到海滩上,对着岸边懒洋洋晒太阳的人冲了过去,鲨鱼居然能在陆地上跳跃,这就是我第一次看到食人鲨的场景,我被它吸引了。食人鲨(Maneater)作国行PS5评测性能提升还能畅玩所有游戏!3099元起作者JimmyMa摄影elvis来源极果编辑部PS5国行终于来啦,对于这款次世代游戏主机来说,小伙伴们肯定关心另外几个问题。国行版本到底能玩哪些游戏?能买吗?数码科技要闻极果君也是EPIC喜加一AmongUs太空版狼人杀,下期神秘游戏你是否期待?大家好,这里是大秦游戏!在上周EPIC的神秘游戏揭晓时,相信很多期待3A大作的朋友们大失所望,但是在真香之后,这部游戏的质量到底如何,我们现在就来看看!amongus是一款非常好玩6月大IP新游戏都来了,你觉得哪款将成为6月的爆款?大家好,我是大秦游戏小编!6月即将到来,摩尔庄园鬼泣少前等多款手游上架公测测试,下面就给大家带来几款6月即将开启测试手游,一起来看看吧!1长安幻想长安幻想是一款新派国风回合手游,你旭旭宝宝在DNF里号召力有多大?第一人吧,毫不过分!旭旭宝宝的号召力其实在他直播生涯中几件事,就可以看出,他对于DNF玩家这个人群的号召力有多大了。号召Dnf各大知名主播与玩家西装打团之前一个网络节目采访一位女大如何评价skt打假赛?今年Skt,是我感觉最弱的一年,也是求胜欲望最弱的一年。首先我们先谈谈打假赛,我认为是不可能,这样做的好处是什么?难道真的打钱,那为什么不多花点直接把冠军买下来得了。今年不想再谈S元气骑士就是不更最新版?老玩家的执着,让萌新笑出了声大家好!我是元气老骑士元气宅。若从一位玩家的角度来看,如果一款游戏发布了最新版本,大多数人的第一反应想必都是点击更新,马上涌入到游戏中去满足自己的好奇心吧。可这款游戏的名字恰好叫做
攻略传世元神版手游攻略各位小伙伴大家晚上好,今天带来传世元神版手游分享开始游戏后,依据游戏提示信息展开前期新手引导,前期经验以放置挂机泡点为主要,当每日任务变为转生每日任务时,角色基本上的功用就全都打开战术攻略术有别,道相通,关于出击时机你都有哪些心得?把握正确的出击时机是胜利的关键荒友们一定要胆大心细把握住每一个微小的时机不给对方留有反应的余地在赛场上切忌鲁莽出击哦一起来看看补漏君的经验所得!借力打力当我们在室内听到脚步声时不要幻塔平民零氪还想SSR武器?有多多云手机辅助武器获取不是问题说到游戏中的等级设定,所有人第一印象是不是就是SSR最高呢?而且,能将SSR凑齐的,不是土豪就是大神,但是在最近得开放幻想风格大世界手游幻塔中,SSR武器变得更加简单,也就是要与众吃鸡新的问题已经出现,可能阻止玩家充Q!奥特曼瑕疵来了务实不浮夸!我是你们的情报小能手,微笑十倍镜。随着吃鸡手游和平精英的不停机更新,奥特曼的第二次联动军需已经实锤!关于它的爆料和测评,最近也是层出不穷!那么奥特曼最大的瑕疵是什么呢?中国玩家对国产单机有多包容?昨日的游戏日报中,我曾报道过两款国产独立游戏亮相,分别是单机独立ACT游戏混沌落日与抗美援朝第一人称射击类游戏代号38N。而昨晚一款名为觉醒者崛起的国产奇幻ARPG游戏试玩Demo诛仙世界毫不避讳?直言测试要分流天刀玩家,网友逆水寒干吗?网络游戏在国内发展已经超过20年,时至今日,已经成为普及度最高竞争最激烈的娱乐产业了。尤其是近些年来手机游戏市场规模不断扩大,全世界的端游市场都在被方便快捷的手游不断蚕食,在这样的梦幻西游网页版首批仙器技登场,你怎么看?蝎子忘川布雨篇接着来看看梦幻西游网页版全新系统仙器技首批放送的内容。少侠们如果有不同的看法,欢迎评论区留言各抒己见。3。蝎子精仙器技蝎子精的特点有很多,肉盾快速附加异常,但最不容易被替代的是她的DNF报名参加闪光杯,需要爆肝才能够完成其中的装备收集任务DNF报名参加闪光杯,需要爆肝才能够完成其中的装备收集任务。如果说DNF最近有什么特别火的活动的话,那自然就是闪光杯了,不仅线上有几十万Q币的奖励,线下更是有几十万现金的,这么一个DNF正式服12月2日更新内容一芝麻开箱有惊喜二玩转阿拉德!第二季三金库惠享礼包四修复bug修复希洛克征战模式中,副本真理的意识之棺拉维茜真理的意识之棺吉里阴影之棺第一个房间无法使用部分消耗品的问题修复像素勇士王者荣耀中那些惊人的操作这样的bug您玩过几个呢?小伙伴们,你们还记得曾经的反向大招姜子牙,达摩一脚把大龙踢出龙坑,最让人惊讶的竟然是他,小霸王孙策。姜子牙这个英雄非常特殊,既可以作为一个法师,也可以作为辅助,有甚者竟然开发边路打Dk公布大名单SHowmaker再秀欠打表情?今年的DK你怎么看?作为S10赛季的冠军战队,DK的实力有目共睹,虽然在S11赛季失去了Nugrui这个大腿,但Khan的表现也并不算很差,夏季赛也是同样夺下了冠军,在世界赛又一次打进决赛,但最终输给