前言

前一阵子遇到了一个头疼两天的问题,如何在项目运行中动态自定义一个以小时为单位的定时任务?我后来想到了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做一个定时任务?相关推荐

  1. Spring整合Redis做数据缓存(Windows环境)

    当我们一个项目的数据量很大的时候,就需要做一些缓存机制来减轻数据库的压力,提升应用程序的性能,对于java项目来说,最常用的缓存组件有Redis.Ehcache和Memcached. Ehcache是 ...

  2. redisdemo php,一个简单的用redis做秒杀支撑的demo (PHP版)

    用redis做秒杀的库存扣除, 限制每个账号只能抢购一次, 这个简单的demo使用了string, hash, list三种基本类型. 用string类型的int值来存储剩余库存, 并在抢购成功后减1 ...

  3. 小妹妹要面试了却没有项目实践的经验,约到奶茶店指导一番,用SpringBoot、Redis、LUA教她做一个!

    前言 那些吧redis基本的东西学的差不多了,却没有做过什么具体的项目实践的,可以看看这篇文章做一个项目来巩固知识. 相关需求&说明 一般来说秒杀系统的功能不会很多,有: 制定秒杀计划.在某天 ...

  4. 我是如何用 Redis 做实时订阅推送的?

    前阵子开发了公司领劵中心的项目,这个项目是以redis作为关键技术落地的. 先说一下领劵中心的项目吧,这个项目就类似京东app的领劵中心,当然图是截取京东的,公司的就不截了... 其中有一个功能叫做领 ...

  5. 学会这几招,你也可以用 Redis 做实时订阅推送!

    作者:浮云骑士LIN 来源:www.cnblogs.com/linlinismine/p/9214299.html 前阵子开发了公司领劵中心的项目,这个项目是以redis作为关键技术落地的. 先说一下 ...

  6. 如何用 Redis 做实时订阅推送的?

    作者:浮云骑士LIN 链接:https://www.cnblogs.com/linlinismine/p/9214299.html 前阵子开发了公司领劵中心的项目,这个项目是以redis作为关键技术落 ...

  7. 【Redis笔记】一起学习Redis | 如何利用Redis实现一个分布式锁?

    一起学习Redis | 如何利用Redis实现一个分布式锁? 前提知识 什么是分布式锁? 为什么需要分布式锁? 分布式锁的5要素和三种实现方式 实现分布式锁 思考思考 基础方案 改进方案 保证setn ...

  8. 领券中心项目,我是如何用 Redis 做实时订阅推送的?

    作者:浮云骑士LIN 出处:cnblogs.com/linlinismine/p/9214299.html 前阵子开发了公司领劵中心的项目,这个项目是以redis作为关键技术落地的. 先说一下领劵中心 ...

  9. php定时执行任务 回调,如何在php中基于workerman实现一个定时任务

    如何在php中基于workerman实现一个定时任务 发布时间:2021-02-15 18:56:14 来源:亿速云 阅读:92 作者:Leah 这篇文章将为大家详细讲解有关如何在php中基于work ...

最新文章

  1. mysql relay log_windows下mysql主从出现Failed to open the relay log(relay_log_pos 248)解决办法...
  2. Android 开发中的多线程编程技术
  3. 要搞清楚对象和对象的引用
  4. 教学案例 计算机,宁夏计算机教学案例
  5. 小米MIX Alpha环绕屏手机还是跳票了,上市时间成迷,小米回应...
  6. 《Head First》 MVC运用的设计模式
  7. 完整BBS系统开发流程及结果展示
  8. java weblogic 下载,weblogic 下载 weblogic 12.2.1 for windows 64位的下载地址
  9. 华山论剑之浅谈XMPP协议实现即时通讯功能
  10. java 时间乱码,Java乱码解决方案
  11. java读取tif文件_java读取TIF,TIFF文件方法
  12. SpringBoot引入Dubbo问题解析
  13. 苹果ios音频的回声消除处理
  14. Axure 9 收录不同效果的制作过程
  15. matlab中如何写出图像第一行到第十行_第一列到第十列之间的数据,Excel中表示从第3列的1行到第10行的单元格引用为()。...
  16. 香蕉派 Banana pi BPI-R2 开源智能路由器 MTK 7623N 方案设计
  17. 分享几个好用的易语言编程助手
  18. Package name does not correspond to the file path (IntelliJ IDEA)
  19. 解决ERROR #42601 syntax error at or near “)“
  20. OpenCore配置错误、故障与解决办法(05-14更新)

热门文章

  1. springboot 集成beetl
  2. Java 编程规范 -- 易错精简版
  3. 优化网站如何看待纯文本外链的作用
  4. Nginx----进阶篇
  5. linux桌面怎么解压tar文件,Linux中tar解压缩命令详解-tar文件怎么打开
  6. 2012百度校园招聘笔试杭州站
  7. CWS(美国国土安全部下属的软件保证项目)与SANS(权威安全培训组织)联合编制的最危险的25个编程错误
  8. 你所不了解的DevOps
  9. 语义版本号(Semantic Versioning)
  10. 6-3 sdust-Java-可实现多种排序的Book类 (20 分)