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

请勿过度依赖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
真的是最后一回合!文明6风云变幻给我们带来了怎样的惊喜就一回合,最后就这么一回合一直以来席德梅尔的文明6在玩家们心中处于一个非常微妙的位置,即便是去年推出资料片迭起兴衰之后也依旧如此。由于这样和那样的问题,在部分人心中文明6远不如前作大家感觉王者荣耀还能活几年?谢谢邀请!各位小伙伴大家好。我是药丸!对于王者荣耀开服到现在也有3年之久了!王者荣耀是腾讯天美工作室于2015年发行的,并命名为王者联盟,经过小段时间的整改才修改为现在的王者荣耀!实况足球潜力新星理查尔里森,来自巴西的天才少年在实况足球手游里面,我们常常提到了潜力股还有即战力这两个概念。潜力股就是现在可能仅仅是金卡或者银卡球员,而在未来很有潜力成为黑卡球员,并且这些球员高突了之后都会有相当不错的水平。但程咬金辅助我忍了,亚瑟辅助我也忍了,谁敢用她辅助直接举报!王者荣耀排位赛选英雄真是个技术活,尤其是呆在五楼的同学,几乎要精通全职业,阵容好不好,很大程度就取决于五楼,因为到五楼选英雄的时候总是剩下辅助位置,而辅助这个职业比较难carry全位移不输韩信,伤害反超猴子,自保堪比李白!她才是新版野区王者在王者峡谷的野区当中,有三个打野英雄可以说是经久不衰,他们分别是位移灵活的韩信,伤害无解的猴子,和自保能力出众的李白。韩信的位移能力在峡谷当中可以说是排得上号了得多了,两个技能就有LOL最帅源计划来了!特效细节满分,比风男亚索更快乐!对于一个资深的lol老玩家来说,皮肤的收藏那肯定是不能放过的,从前的皮肤,官方十分不注重特效的变化,所以当时卖的只是老玩家们对它的情怀,但是后来官方发现了这个问题,近期不断的对皮肤猎天使魔女中的魔女形象溯源15世纪以降的欧洲,正笼罩在对巫术的恐慌之中。自古以来有着黑白之分的传统巫术信仰,因其与基督教教义的相悖而成了迷信的代名词。无论是诅咒人的黑巫术,还是治愈人的白巫术,一齐统括在了魔第五人格预防爆点的7大常识,第4点虐哭机皇在第五人格里,监管者想要抓住求生者,首先就需要确定求生者的位子,尤其是在中高端局里,有些屠夫直接背熟了出生点,一开局就跟你愉快打招呼。如何在求生局里避免暴露自己的位子,在最大的生存玩多了,身体一天不如一天,玩家这谁顶得住?GTA5是一款来自于国外的游戏,在国内也受到了很大的关注,这实际上也是和我们早年间接触的罪恶都市以及圣安地列斯有一定关系存在的,当年红遍整个网吧的游戏,现在出了续作,能不受欢迎吗,DNF玩家搬出45独立卡片,一管疲劳收益7000w?摇身一变成欧皇新版本上线已经有一个月的时间了,在这段时间中很多欧皇玩家已经毕业泰波尔斯装备,相比起那些还在攒材料来升级的玩家快了很多。每次版本更新都会给我们带来不同的内容,对于那些还没有达到超时Uzi真人拳击视频爆出,这手速。。。网友不敢乱黑了最近浏览网页,偶然发现了枣子哥拳击视频。都知道枣子哥是LOL职业选手,AD位置传奇人物,操作和意识都没得说。虽然在S8世界赛上意外爆冷淘汰,但是实力和影响力还是摆在那里,前段时间还
从EDG夺冠看电子竞技行业摘要从消除误区走向快速发展阶段。电子竞技行业在中国经历了一波三折的发展。2008年,国家体育总局将电子竞技改批为第78个正式体育竞赛项目,获得官方认可。目前,电子竞技正围绕着专业化LCK首发挑战赛管泽元解说罕见发怒,GEN举动引不满随着LPL赛区和LCK赛区转会消息的落幕,各个队伍的新阵容引起了众多玩家关注。特别是LCK赛区的战队,因为LPL赛区有德杯比赛可以提前以赛代练展现一下队伍的实力,而LCK队伍的实力王者荣耀镜KPL新皮肤局内特效皮肤价格及上架时间王者荣耀KPL总决赛将在本月底开启,全新KPL皮肤打野位置属于镜,镜KPL皮肤会在下周上线,首周折扣532点券,属于史诗品质且限定,皮肤系列是KPL匿光小队,一起来看看特效吧。王者DOTA2QC一号位选手点评队内新人,年轻人总是充满活力QC战队一号位Yawar最近接受了采访。在接受采访时,他谈到了球队对本赛季的期待,以及对刚刚加盟球队的新球员的看法。在谈论DPC联赛中QC的现状时。Yawar说他们的状态非常好,他Telltale将会在明年公布新作我们身边的狼2的详细信息今日,TelltaleGames在推特中表示将会在2022年公布更多关于旗下经典之作我们身边的狼的第二部的消息。作为2013年我们身边的狼的续作,我们身边的狼2早在TGA2019已王者荣耀s26赛季即将开启8款皮肤将会优化。新赛季很快就要到了,从这个赛季的战令来看,不出意外新赛季应该是在一月十号左右开启。满打满算就剩下不到20的时间了,小伙伴们可要抓紧上分咯,上个王者应该是不成为问题的。另外在新赛季中金铲铲之战比大嘴更好玩的阵容,简单且暴力,恰烂分必备玩法各位自走棋的小伙伴们大家好,众所周知,金铲铲之战玩的就是阵容搭配,只要有发牌员按着你的思路来,那么即便是一群小费英雄组合到一起,也能给你发挥出超常的实力。这就好比之前的圣盾大嘴套路真人影像互动式游戏迷惑Deluded调查某个肇事案件故事梗概一个经典的肇事类型案件。扮演警探本人,与您的助手苏珊一起努力查清这个案件。在调查中要注意细节,找到线索和证据,解答谜题,确保您已经准备好面对自身的恶魔并回答所有问题,因为您精苏狂喜!战舰世界全球同新,S系航母开放研发从1918年完全按照航母设计的竞技神号开工,航空母舰作为一个独立舰种,现如今已走过百年历程。说起航空母舰,多数人第一时间肯定会想到火力强大技术先进的美国航母,当然也要有人会谈到我国2021GESC勇闯天涯superX贵州省电子竞技大赛即将火热开启2021GESC勇闯天涯superX贵州省电子竞技大赛暨TGA贵州省预备队选拔赛总决赛即将于本周六(12月25日)在汇金星力城火热开赛。届时,英雄联盟(端游)及王者荣耀(手游)两个Deft谈Uzi复出给出最高评价,是最敬佩2个AD之一,UZI带来坏消息小伙伴们大家好,欢迎您收看本期游戏资讯,我是小米!自从Uzi复出加盟BLG之后,成了各大赛区议论的焦点,有不少选手都发表了自己的看法,特别是我们隔壁的LCK赛区,更是对其极其关注,