专栏电商日志财经减肥爱情
投稿投诉
爱情常识
搭配分娩
减肥两性
孕期塑形
财经教案
论文美文
日志体育
养生学堂
电商科学
头戴业界
专栏星座
用品音乐

请勿过度依赖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
疯狂电路物理老师我对不起你们,一个游戏我都玩不明白了这两天无意中发现一个关于学习的游戏疯狂电路。终于可以光明正大的说,我玩游戏就是为了学习,等我把这个游戏通关我就成为电路小能手了。这游戏把物理电路的各个知识点植入进关卡当中,随着闯关红色警戒之几乎完美的尤里复仇心灵终结2。0各个版本没错,这次说的是心灵终结2。0系列。对,不是人尽皆知的3。0系列,而是2。0系列。没错,就是他3。0和2。0老玩家应该知道,心灵终结系列有一个美名几乎完美的尤里复仇这行字在2。0p红色警戒单位介绍公认最强特色单位巨炮没错,今天要介绍的是红色警戒法国的特色单位,巨炮。开战一个多月投降,我真厉害开场笑话说它是整个红警性价比最高的特色单位应该没人反驳吧?射程是防御建筑里当之无愧的最远,足足有14格,红色警戒单位介绍说说战机那些技巧和实战用法首先我们要知道,红警二里是有两种战机的,入侵者和黑鹰。入侵者是盟军通用,黑鹰则是棒子国专属。因为黑鹰是特色兵种,在纸面数据更强的情况下,价格和入侵者一模一样。入侵者战机相比黑鹰,入和平精英加qq群领皮肤,要微信账号密码。可信吗?不可信,亲身经历!我是抠抠解说吖,专注做好看好玩的和平精英视频,欢迎大家前来观看。作为一名和平精英玩家,平时自然少不了逛一逛世界聊天频道,在这里面聊天的玩家可谓鱼龙混杂,各种各样的红色警戒单位介绍共和国之辉中国专属喷火碉堡,天启绝配既然上一期说的是碉堡,这一期就给大家讲讲共和国之辉版本里中国的专属碉堡cn整体军备共和国之辉是一个比较大众的mod,虽然平衡性仍然一般但有了不少有趣的改动。而其中cn作为主角阵营自红色警戒单位介绍美国特色兵种伞兵战力几何?我们都知道,游戏里美国的特色兵种是免费的伞兵,需要由空指部解锁,一次8个,那么这个兵种的战略价值到底怎样,以及怎样更好的利用呢?肯定有人会觉得,一次只有八个,空降的飞机还有可能会被SNH48刘增艳2021年八选拉票大家好,我是刘增艳。在2021年的总选来得比以往夏天要来的晚一些,但是停靠在场馆门口的大巴比以往的大,比以往要开走的早一些。不知道从什么时候开始呢,我们的总选变成了一场饥饿游戏,我在王者荣耀里请别人当师父需要一开始给他送皮肤吗?这个问题,我们可以做一个很好的比喻。目前网络直播盛行,有不少人在观看直播时会对主播进行打赏,很多人对此事嗤之以鼻,绝对打赏的人就是傻子,其实不然。你是否要对其进行打赏,是根据你自己lol五个路人(钻石)击败职业战队的概率是否为0?可以很确定的说,LOL五个路人(钻石水平玩家)击败职业战队的概率为0!这一点都不夸张,即使是5个路人王者,击败职业战队的概率也一样为0。有一句话是这么说的,请你要用你的业余爱好去挑红色警戒单位介绍特色单位中的利器辐射工兵辐射工兵在红色警戒二里基本上算是除巨炮以外最好用的特色兵种了。相比较于英国狙击手,辐射工兵的射速更快,血量更厚,可以快速清一大片步兵并且兼顾反坦克,部署值得注意的是辐射工兵在正常使
微软不惜将AAA级游戏作筹码要求在iOS端运行xCloud但仍遭苹果拒绝在深入挖掘Epic诉苹果的法庭文件之后,国外科技媒体TheVerge从一些私人电子邮件中挖出重磅消息在AppStore运行云游戏平台xCloud方面,微软曾私下找苹果寻求解决方案,王者荣耀虎年特效爆料,体验服UI优化,历练值获取方式增加大家好,我是七七。今年的春节比往年要早,爆料也比往年要来得早。有玩家在回城特效中发现了一个标注着虎年限定的回城,点开之后发现,这个特效确实是一个新的特效。特效中出现了五个图案,说明LPL转会期最新消息V5组建银河战舰,Bin加入RNG,小虎回归中路LPL转会期即将临近,将在下周一结束转会期,各战队的消息基本尘埃落定,我们也有了更多精确的消息爆料,Theshy确认加入WBG,原辅助蛇蛇确认回归,Rookie与Karsa加盟V5阴阳师3颗黑蛋补偿计划回归,突然的阳间让人担忧12月活动导读不知道痒痒鼠们是否还记得,SP面灵气这位式神自从11月中旬开始就在体验服进行调整,而前几日也终于敲定了最终版的技改方案。(应该不会再改动了)而与之相关的黑蛋补偿问题,自从更改成TGA2021颁奖典礼信息汇总心灵杀手2星球大战日蚀等新作公布TGA2021颁奖典礼于12月10日上午举行,和往年一样,持续数小时的活动除了颁出一系列玩家关心的年度游戏奖项以外,还公布了海量游戏影视的预告视频,足球经理2022教练怎么聘请?教练聘请指南足球经理2022教练怎么聘请?教练聘请是非常重要的事情,很多玩家都不知道该怎么做,下面小编就带来足球经理2022教练聘请指南,一起来看看吧。足球经理2022教练聘请指南有些老队员准王者荣耀S26赛季下月开启,战令奖励公布,韩信孙悟空笑了时过境迁,转眼间12月份已经进入中旬了,王者本赛季也即将结束,让我们喜迎新赛季的到来,那新赛季将是王者的第26个赛季,S26新赛季将在下月份开启,应该在2022年1月5号期间,其次王者荣耀吕布的细节操作,别以为吕布是个无脑英雄Hello大家好,我是金仔。今天来给大家解说一下王者荣耀吕布的玩法以及怎么才能玩好吕布。首先来给大家讲一下吕布的技能,吕布的一技能是带有真实伤害的,无论对面的敌人有多肉,只要吕布一原神为啥送出2400原石,网友可能来源于幻塔压力2。3版本期间原神连获3奖,总共送出2400原石。为被优菈阿贝多双复刻池子,掏空钱包的旅行者带来一丝安慰。原神获奖实至名归。无论在流水方面还是质量方面,原神在手游赛道中的表现都很抢你认为最能代表DotA精神的装备(物品)是哪件?这个问题很有意思!dota和dota2作为最成功的竞技游戏之一,游戏里不仅有很多经典的英雄,各式各样道具也是它的魅力所在!要说具有dota精神的道具,能说出很多件!下面我来盘点一下英雄联盟里面,美国英雄有流浪法师,日本英雄有影流之主,中国英雄有什么?那肯定是齐天大圣孙悟空啊,只有孙悟空才是我们中国文化独有的产物。孙悟空被我们称为斗战胜佛,是中国最能打的象征,随着电影行业在中国的发展,很多神话玄幻题材的电影也开始向孙悟空下手,我
友情链接:快好知快生活快百科快传网中准网文好找聚热点快软件