请勿过度依赖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
疯狂电路物理老师我对不起你们,一个游戏我都玩不明白了这两天无意中发现一个关于学习的游戏疯狂电路。终于可以光明正大的说,我玩游戏就是为了学习,等我把这个游戏通关我就成为电路小能手了。这游戏把物理电路的各个知识点植入进关卡当中,随着闯关
红色警戒之几乎完美的尤里复仇心灵终结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。有一句话是这么说的,请你要用你的业余爱好去挑
红色警戒单位介绍特色单位中的利器辐射工兵辐射工兵在红色警戒二里基本上算是除巨炮以外最好用的特色兵种了。相比较于英国狙击手,辐射工兵的射速更快,血量更厚,可以快速清一大片步兵并且兼顾反坦克,部署值得注意的是辐射工兵在正常使