基于Redis的定时任务
最近遇到一个业务场景,某次活动开始后要在250秒后自动关闭,然后修改活动的状态。考虑一下可以用传统的定时任务去处理
- 会出现250秒时间的延时问题,比如某次任务刚刚结束,但是定时任务在前一秒就结束了,那么活动虽然结束了,那么还要再等一个定时任务才能执行,时效性不行。
针对这个业务需求,我们采用 Redis (2.8.0+版本)的订阅发布模式 ,当key过期时触发相关事件。
redis配置
Redis 配置文件的具体配置:
#
# Example 2: to get the stream of the expired keys subscribing to channel
# 获取订阅channel的过期的key
# channel名称: __keyevent@0__:expired
#
notify-keyspace-events Ex
#
# By default all notifications are disabled because most users don't need
# this feature and the feature has some overhead. Note that if you don't
# specify at least one of K or E, no events will be delivered.
# 默认情况下,所有通知都被禁用,因为大多数用户不需要这个功能和功能有一些开销
# 请注意,如果没有指定K或E中的至少一个,不会传送任何事件。
#
# notify-keyspace-events ""
redis.conf 的配置如上,我也加上了相关注释。
jfinal配置
public class LmsCoreConfig extends JFinalConfig {
/**
* 启动后回调,使用异步,不然线程阻塞
*/
public void afterJFinalStart() {
FutureTask futureTask = new FutureTask(() -> {
Redis.use().getJedis().subscribe(new KeyExpiredListener(), "__keyevent@0__:expired");
return null;
});
ExecutorService executorService = Executors.newFixedThreadPool(1);
executorService.submit(futureTask);
}
}
/**
* 监听redis key过期的监听器
*/
public class KeyExpiredListener extends JedisPubSub {
@Override
public void onMessage(String channel, String message) {
// message 对应 key值
//TODO key过期后的业务代码。
}
}
测试
我们通过redis-cli 设置几个有过期时间的key测试一下
127.0.0.1:6379> SET test 123
OK
127.0.0.1:6379> EXPIRE test 60
(integer) 1
60秒触发KeyExpiredListener监听器