如何使用redis做一个定时任务?
前言
前一阵子遇到了一个头疼两天的问题,如何在项目运行中动态自定义一个以小时为单位的定时任务?我后来想到了redis键空间,用来监听过期的key,结合存储的执行间隔,重新存储有效期的key。
正文
查了查大佬们的文章,简单学习后,了解了redis键空间的用法和基本的知识。
什么是redis键空间?
Redis的键空间通知:keyspace notifications
这个功能是在2.8版本后加入的,在客户端通过订阅鸡汁,来接收那些以某种方式改变了redis数据空间的事件通知。
比如说,改变key的命令;所有在0号库过期的key;
事件类型
改变redis数据空间的每个操作,键空间通知都会发送两个不同的事件。
比如在1号数据库,执行 del zhangsan 的操作,将会触发两个消息:
1、keyevent@1:del zhangsan
2、keyspace@1:zhangsan del
keyspace是对所有zhangsan的key操作进行监听的。
keyevent是对所有执行成功的del操作进行监听,
如果有订阅者订阅监听了他,则会收到zhangsan返回的通知。
我就是利用了可以接收某个库过期的key这个操作,完成了这个定时任务。
而这个功能是可以通过redis配置来实现的,下面来说下到底怎么修改这个配置。
redis配置
因为键空间通知会消耗一定的CPU时间,所以在默认情况下,redis是关闭这个功能的,我们需要手动修改redis.conf来修改此功能的开启状态。
找到配置中 # notify-keyspace-events去掉注释,然后重新启动redis就可以了,easy吧?
这条配置,是需要在后面加多个指定的字符组成,来代表其不同的功能:
K:keyspace事件,事件以__keyspace@<库名>__为前缀进行发布;
E:keyevent事件,事件以__keyevent@<库名>__为前缀进行发布;
g:一般性的,非特定类型的命令,比如del,expire,rename等;
$:字符串特定命令;
l:列表特定命令;
s:集合特定命令;
h:哈希特定命令;
z:有序集合特定命令;
x:过期事件,当某个键过期并删除时会产生该事件;
e:驱逐事件,当某个键因maxmemore策略而被删除时,产生该事件;
A:g$lshzxe的别名,因此”AKE”意味着所有事件。
这些选项中,至少要包含K或者E,否则就没啥用了
比如我在这个定时任务中,使用了E和x:notify-keyspace-events Ex
话不多说了,上菜!
@Configuration
public class RedisConfiguration {@Autowiredprivate RedisTemplate redisTemplate;@Autowiredprivate RedisConnectionFactory redisConnectionFactory;@Bean(name = "redisTemplate")public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) {RedisTemplate<String, String> template = new RedisTemplate<>();template.setConnectionFactory(factory);template.setKeySerializer(new StringRedisSerializer());template.setValueSerializer(new GenericJackson2JsonRedisSerializer());template.setHashKeySerializer(new GenericJackson2JsonRedisSerializer());template.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());template.afterPropertiesSet();return template;}/*** 监听key过期事件*/@Beanpublic RedisMessageListenerContainer redisMessageListenerContainer() {RedisMessageListenerContainer container = new RedisMessageListenerContainer();container.setConnectionFactory(redisConnectionFactory);return container;}/*** 指定监听库*/@Beanpublic ChannelTopic expiredTopic() {return new ChannelTopic("__keyevent@1__:expired");}}
expiredTopic()方法,就可以指定某个库,某个事件,expired就是过期啦。
@Component
@Slf4j
public class RedisKeyExpirationListener extends KeyExpirationEventMessageListener {public RedisKeyExpirationListener(RedisMessageListenerContainer listenerContainer) {super(listenerContainer);}/*** 失效后回调函数* @param message* @param pattern*/@SneakyThrows@Overridepublic void onMessage(Message message, byte[] pattern) {super.onMessage(message, pattern);String msg = new String(message.getBody(), "UTF-8");String channel = new String(message.getChannel(), "UTF-8");log.info("Redis-Listener Channel:"+channel+" Listen to the key:"+msg);//msg字符串处理,获取想要的key名字....//具体的业务处理//想要定时,那就继续把key存到redis,结合过期时间}}
正菜就是这些,具体业务还是需要结合不同项目,这里就不单独写我的了,至于怎么重新存储redis,这就不再多说了,工具类一找一大堆的哇!
总结
测试类我就不写出来了,自己动动手,马上就明白了这个redis键空间的用法。
可能这个功能会再以后运行中出现一些问题,在这里提几个,提前有所准备吧!比如说:
1、redis挂了?
2、一般来说这种动态定时不是很多,可如果很多,占内存或者影响速度怎么办?
3、反复启停定时,是否影响redis的其它操作?如果影响了,怎么办?
4、redis的订阅发布模式是fire and forget模式,发了就扔了,所以说收不到咋办,定时不存啦?
5、如果订阅发布的客户端over了又重连,岂不是事件都丢了?
好啦,大概提几个可能遇到的,我就不单独去说了,毕竟我也还没遇到咧!我这个项目比较小,问题也不大。但真的也要留心,任何一个错误,都不是小事!
希望对大家有点帮助!我是左小涩,一个独自在大城市努力的年轻人。
如何使用redis做一个定时任务?相关推荐
- Spring整合Redis做数据缓存(Windows环境)
当我们一个项目的数据量很大的时候,就需要做一些缓存机制来减轻数据库的压力,提升应用程序的性能,对于java项目来说,最常用的缓存组件有Redis.Ehcache和Memcached. Ehcache是 ...
- redisdemo php,一个简单的用redis做秒杀支撑的demo (PHP版)
用redis做秒杀的库存扣除, 限制每个账号只能抢购一次, 这个简单的demo使用了string, hash, list三种基本类型. 用string类型的int值来存储剩余库存, 并在抢购成功后减1 ...
- 小妹妹要面试了却没有项目实践的经验,约到奶茶店指导一番,用SpringBoot、Redis、LUA教她做一个!
前言 那些吧redis基本的东西学的差不多了,却没有做过什么具体的项目实践的,可以看看这篇文章做一个项目来巩固知识. 相关需求&说明 一般来说秒杀系统的功能不会很多,有: 制定秒杀计划.在某天 ...
- 我是如何用 Redis 做实时订阅推送的?
前阵子开发了公司领劵中心的项目,这个项目是以redis作为关键技术落地的. 先说一下领劵中心的项目吧,这个项目就类似京东app的领劵中心,当然图是截取京东的,公司的就不截了... 其中有一个功能叫做领 ...
- 学会这几招,你也可以用 Redis 做实时订阅推送!
作者:浮云骑士LIN 来源:www.cnblogs.com/linlinismine/p/9214299.html 前阵子开发了公司领劵中心的项目,这个项目是以redis作为关键技术落地的. 先说一下 ...
- 如何用 Redis 做实时订阅推送的?
作者:浮云骑士LIN 链接:https://www.cnblogs.com/linlinismine/p/9214299.html 前阵子开发了公司领劵中心的项目,这个项目是以redis作为关键技术落 ...
- 【Redis笔记】一起学习Redis | 如何利用Redis实现一个分布式锁?
一起学习Redis | 如何利用Redis实现一个分布式锁? 前提知识 什么是分布式锁? 为什么需要分布式锁? 分布式锁的5要素和三种实现方式 实现分布式锁 思考思考 基础方案 改进方案 保证setn ...
- 领券中心项目,我是如何用 Redis 做实时订阅推送的?
作者:浮云骑士LIN 出处:cnblogs.com/linlinismine/p/9214299.html 前阵子开发了公司领劵中心的项目,这个项目是以redis作为关键技术落地的. 先说一下领劵中心 ...
- php定时执行任务 回调,如何在php中基于workerman实现一个定时任务
如何在php中基于workerman实现一个定时任务 发布时间:2021-02-15 18:56:14 来源:亿速云 阅读:92 作者:Leah 这篇文章将为大家详细讲解有关如何在php中基于work ...
最新文章
- mysql relay log_windows下mysql主从出现Failed to open the relay log(relay_log_pos 248)解决办法...
- Android 开发中的多线程编程技术
- 要搞清楚对象和对象的引用
- 教学案例 计算机,宁夏计算机教学案例
- 小米MIX Alpha环绕屏手机还是跳票了,上市时间成迷,小米回应...
- 《Head First》 MVC运用的设计模式
- 完整BBS系统开发流程及结果展示
- java weblogic 下载,weblogic 下载 weblogic 12.2.1 for windows 64位的下载地址
- 华山论剑之浅谈XMPP协议实现即时通讯功能
- java 时间乱码,Java乱码解决方案
- java读取tif文件_java读取TIF,TIFF文件方法
- SpringBoot引入Dubbo问题解析
- 苹果ios音频的回声消除处理
- Axure 9 收录不同效果的制作过程
- matlab中如何写出图像第一行到第十行_第一列到第十列之间的数据,Excel中表示从第3列的1行到第10行的单元格引用为()。...
- 香蕉派 Banana pi BPI-R2 开源智能路由器 MTK 7623N 方案设计
- 分享几个好用的易语言编程助手
- Package name does not correspond to the file path (IntelliJ IDEA)
- 解决ERROR #42601 syntax error at or near “)“
- OpenCore配置错误、故障与解决办法(05-14更新)